要以PDF格式阅读本主题,请点击这里

演员

GPars 中的演员支持受到 Scala 中演员库的启发,但随后已经超越了它。

演员允许基于消息的并发模型,由独立的活动对象构建,这些对象交换消息且没有可变的共享状态。 演员可以帮助解决或避免死锁、活锁或饥饿等问题,这些问题是共享内存的典型问题。 Ruben Vermeersch 最近对演员背后的关键概念进行了很好的总结。

内部演员

演员可以共享一个相对较小的线程池。 这可以扩展到许多并发演员共享一个单一的池化线程。 它们避免了 JVM 的线程限制。

演员代码以块的形式处理,块之间由等待新事件(消息)的静默期隔开。 这可以通过延续自然地建模。

由于 JVM 不直接支持延续,因此必须在演员框架中模拟它们,这对演员代码的组织有轻微的影响。 但是,在大多数情况下,好处 outweighs 困难。

演员示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import groovyx.gpars.actor.Actor
import groovyx.gpars.actor.DefaultActor

class GameMaster extends DefaultActor {
    int secretNum

    void afterStart() {
        secretNum = new Random().nextInt(10)
    }

    void act() {
        loop {
            react { int num ->
                if (num > secretNum)
                    reply 'too large'
                else if (num < secretNum)
                    reply 'too small'
                else {
                    reply 'you win'
                    terminate()
                }
            }
        }
    }
}

class Player extends DefaultActor {
    String name
    Actor server
    int myNum

    void act() {
        loop {
            myNum = new Random().nextInt(10)
            server.send myNum
            react {
                switch (it) {
                    case 'too large':
                        println "$name: $myNum was too large"
                        break
                    case 'too small':
                        println "$name: $myNum was too small"
                        break
                    case 'you win':
                        println "$name: I won $myNum"; terminate()
                }
            }
        }
    }
}

def master = new GameMaster().start()
def player = new Player(name: 'Player', server: master).start()

[master, player]*.join()

Jordi Campos i Miralles,巴塞罗那大学,数学系,应用数学与分析系提供示例

演员的使用

有关演员的更多详细信息,请访问参考书中的演员部分

请查看众多演员演示