之所以叫主动对象, 区别于被动对象, 只能被动被别人调用的对象, 而主动对象内部有线程可以自行调用自己的方法.
Active Object首先使用了Proxy模式, 这个和RPC一样, 用户可以象访问local function一样使用
然后Active Object关键的一步是使用command模式分离invacation和execution, proxy并没有直接运行调用逻辑, 而是封装成command发送给invoker queue
Active Object 设计模式的本质是解耦合方法的调用 (Method invocation) 与方法的执行 (Method execution), 方法调用发生在调用者线程, 而方法的执行发生在独立于调用者线程的Active Object线程, 并且这个过程对用户透明.
在 Active Object 模式中,主要有以下几种类型的参与者:
- 代理 (Proxy) :代理是Active Object所定义的对于调用者的公共接口. 运行时代理运行在调用者线程的上下文中, 负责把调用者的方法调用转换成相应的方法请求(Method Request), 并将其插入相应的Activation Queue, 最后返回给调用者Future对象
- 方法请求(Command):方法请求定义了方法执行所需要的上下文信息, 诸如调用参数等
- Activation Queue:负责存储所有由代理创建的, 等待执行的方法请求. 从运行时来看, Activation Queue会被包括调用者线程及其Active Object线程并发存取访问, 所以Activation Queue实现应当是线程安全的
- 调度者(Scheduler):调度者运行在Active Object线程中, 调度者来决定下一个执行的方法请求, 而调度策略可以基于很多种标准, 比如根据方法请求被插入的顺序FIFO或者LIFO, 比如根据方法请求的优先级等等
- Implementer(Servant): Implementer是Proxy所定义的接口的实际执行者
- Future: 调用者调用Proxy所定义的方法, 获得Future对象. 调用者可以从该Future对象获得方法执行的最终结果. 在真实的实现里, Future对象会保留一个私有的空间, 用来存放Implementer方法执行的结果
Active Object模式不属于《Design Pattern》23模式。实际上,她是一种特殊的Command Queue。其特殊之处在于:
1. 队列的拥有者会顺序地执行队列中所有Command对象的Execute方法。(这个其实不算特殊)
2.Command对象在自己的Execute方法结束前,可以把一个新的command对象(实际上常常是这个command对象自己)再加到队列的尾部。
看出来了吗,这个队列有可能不会终止的,他可以一直执行下去。这个可以作为一个应用或者服务的主模块了,想像一下她可以作多少事情吧。
《ASP》指出这个模式可以用来在一个线程中处理多任务的问题!!! ^_^ 太cool了。
如何处理呢?你可以把每个command对象看作是一个任务。他在Execute函数中,处理自己的任务,在任务告一段落时,记录自己的状态,然后把自己插入到队列的尾部,结束Execute方法。当队列轮完一周后,又会再次执行这个command对象的Execute方法。 ^_^ 很cool吧。
那么这种方法和多线程的方法相比有什么有缺点呢?
最大的优点是,所有的command都在同一个线程中,因此切换时,不需要进入内核模式!!超高效啊!!而且,可以有很多很多的command,数量上远远超过多线程的数量。
缺点嘛,是这种方法需要用户自己来实现调度,另外这其实是一种非剥夺模式的多任务,如果command处理不好,就会连累其它所有的command,因此实际上比多线程要更复杂。(嘿嘿,程序员能够怕麻烦吗?)
还有一点,Active Object运行于单线程,也就是说,她不能享受多处理器或多处理器核心带来的性能上的改善。
其实,这最后一点是非常致命的一点。也就是说,在当前intel的超线程CPU机器上,如果系统的负担并不重的时候。Active Object的效率有可能比多线程更低。
Anyway,这是一个非常有趣的模式。只是一般的程序员可能没有机会用到。但是请记住她,也许能有那么一次机会,可一用她来爽上一把。
参考: