要以 PDF 格式阅读此主题,请点击此处。 |
代理
代理是一种特殊用途的线程安全非阻塞实现,其灵感来自 Clojure 中的代理。
简介
代理通过只允许单个**代理管理线程**对它们进行修改来保护可变值。可变值**不能直接从外部访问**,而是必须**将请求发送到代理**,代理保证以调用者的身份顺序处理请求。代理保证所有请求的顺序执行,从而保证值的 一致性。
代理是异步活动对象,接受代码(函数)作为消息。接收后,函数将针对代理的内部状态运行,函数的返回值被认为是代理的新的内部状态。
示意
代理示例
1
2
3
4
5
6
agent = new Agent(0) //created a new Agent wrapping an integer with initial value 0
agent.send {increment()} //asynchronous send operation, sending the increment() function
...
//after some delay to process the message, the internal Agent's state has been updated
...
assert agent.val== 1
为了包装整数,我们当然可以使用 Java 平台的*AtomicXXX*类型。当状态或更新算法变得更复杂时,我们需要更多的支持。
示例
另一个示例
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
import groovyx.gpars.agent.Agent
/**
* Conference stores the number of registrations and allows parties to register and unregister.
* It inherits from the Agent class and adds the register() and unregister() private methods,
* which callers may use it the commands they submit to the Conference.
*/
class Conference extends Agent<Long> {
def Conference() { super(0) }
private def register(long num) { data += num }
private def unregister(long num) { data -= num }
}
final Agent conference = new Conference() //new Conference created
/**
* Three external parties will try to register/unregister concurrently
*/
final Thread t1 = Thread.start {
conference << {register(10L)} //send a command to register 10 attendees
}
final Thread t2 = Thread.start {
conference << {register(5L)} //send a command to register 5 attendees
}
final Thread t3 = Thread.start {
conference << {unregister(3L)} //send a command to unregister 3 attendees
}
[t1, t2, t3]*.join()
assert 12L == conference.val
有关最新更新,请参阅用户指南中的代理部分以及相应的演示。