Agents

Agents 是用把一些事情放到另外一个线程来做 -- 一般来说不需要事务控制的。它们对于修改一个单个对象的值(也就是Agent的值)来说很方便。这个值是通过在另外的一个thread上面运行一个“action”来修改的。一个action是一个函数, 这个函数接受Agent的当前值以及一些其它参数。 Only one action at a time will be run on a given Agent在任意一个时间点一个Agent实例上面只能运行一个action.

agent 函数可以建立一个新的Agent. 比如:

(def my-agent (agent <em>initial-value</em>))

send 函数把一个 action 分配给一个 Agent, 并且马上返回而不做任何等待。 这个action会在另外一个线程(一般是由一个线程池提供的)上面单独运行。 当这个action运行结束之后,返回值会被设置给这个Agent。 send-off 函数也类似只是线程来自另外一个线程吃。

send 使用一个 "固定大小的" 线程吃 (java.util.concurrent.Executors里面的 newFixedThreadPool) ) , 线程的个数是机器的处理器的个数加2。如果所有的线程都被占用,那么你如果要运行新的action, 那你就要等了。 send-off 使用的是 "cached thread pool" (java.util.concurrent.Executors里面的? newCachedThreadPool) ) , 这个线程池里面的线程的个数是按照需要来分配的。

如果 send 或者 send-off 函数是在一个事务里面被调用的。 那么这个action直到线程提交的时候才会被发送给另外一个线程去执行。这在某种程度上来说和 commute 函数对 Ref 的作用是类似的。

在action里面, 相关联的那个agent可以通过symbol: *agent* 得到。

await 以一个或者多个Agent作为参数, 并且block住当前的线程,直到当前线程分派给这些Agent的action都执行完了。 await-for 函数是类似的, 但是它接受一个超时时间作为它的第一个参数, 如果在超时之前事情都做完了, 那么返回一个非nil的值, 否则返回一个非nil的值,而且当前线程也就不再被block了。 awaitawait-for 函数不能在事务里面调用。

如果一个action执行的时候抛出一个异常了,那么你要dereference这个Agent的话也会抛出异常的。在action里面抛出的所有的异常可以通过 agent-errors 函数获取。 clear-agent-errors 函数可以清除一个指定Agent上面的所有异常。

shutdown-agents 函数等待所有发送给agents的action都执行完毕。然后它停止线程池里面所有的线程。在这之后你就不能发送新的action了。我们一定要调用 shutdown-agents 以让JVM 可以正常退出,因为Agent使用的这些线程不是守护线程, 如果你不显式关闭的话,JVM是不会退出的。