角色是一种能够接收消息、处理请求以及发送响应的自由运行的活动(activity),主要被设计用来支持异步化且高效的消息传递机制。
每个角色都有一个内建的消息队列,该队列与手机上所使用的短信队列十分相似。假设Sally和Sean同时给Bob的手机发了短信,则运营商将会把这两条短信都保存起来以便Bob在方便的时候取走。类似地,基于角色的并发库允许多个角色并发地发送消息。默认情况下,消息发送者都是非阻塞的;它们会先把消息发送出去,然后再继续处理自己的业务逻辑。类库一般会让特定的角色顺序地拾取并处理消息队列中消息,只有将当前消息处理完或将消息委派给其他角色并发处理之后,这个角色才能够接收下一个消息。
角色的生命周期如图 8‑1所示。一个角色在被创建出来之后既可以被启动也可以被终止。一旦被启动,角色即已准备就绪,随时可以接收/处理消息。当角色处于活动状态时,则不是在处理消息就是在等待新消息到达。而一旦停止之后,角色就不会再接收任何消息了。就角色的整体生命周期而言,其用于等待和处理消息的耗时比取决于它们所处的应用程序的动态特性。
图 8‑1 角色对可变状态进行了隔离,不同角色之间通过传递不可变消息来进行通信 |
如果角色在程序的设计中起到了举足轻重的作用,那么我们就会期望在程序执行过程中创建足够多可供使用的角色。然而线程是有限的资源,所以我们不能把角色与线程一对一地捆绑在一起。为了避免资源不足的问题,支持角色的类库通常都会将角色与线程解耦。角色与线程之间的关系好比公司食堂和公司雇员。例如,Bob在其公司食堂里是没有专门的座位的(如果他想要这种待遇的话恐怕得另找一份工作了),所以每次他去食堂吃饭都是随便找一个没人占的座位就行了。与此相类似地,当收到一个待处理的消息或待运行的任务时,角色就可以分配到一个可用的线程来执行任务。一个好的角色在不执行任务时是不会占住线程不放的,因为只有这样才能够让更多不同状态下的角色处于活动状态,并将有限的可用线程资源充分地利用起来。虽然在任意时刻都可能有多个角色处于活动状态,但在任何情况下一个角色中只有一个线程是活动的。这样既保证了多个角色之间的并发性,同时又消除了单个角色之内的竞争。