二. 主动对象(Active Object)模式

主动对象模式是一种用于并发编程的模式,它通过分离方法调用和执行,提高了并行性和降低了异步访问的复杂性。该模式常用于多线程和分布式系统,简化了对内部拥有控制线程的对象的异步调用。模式中包含代理者、执行者、调度者等组件,确保了调用不会阻塞整个进程,简化了共享对象的同步逻辑,并允许并行执行操作。通信网关是一个实际应用例子,展示了如何使用主动对象模式处理多个TCP连接的并发数据传输,提高系统效率。
摘要由CSDN通过智能技术生成

原标题:Active Object -An Object Behavioral Pattern for Concurrent Programming
源文地址:http://www.cs.wustl.edu/~schmidt/PDF/Act-Obj.pdf
译 者:cuichaox@gmail.com

译者注:
1.    对象分为主动对象和被动对象,主动对象内部包含一个线程,可以自动完成动作或改变状态,而一般的被动对象只能通过被其他对象调用才有所作为。在多线程程序 中,经常把一个线程封装到主动对象里面。
2.    在翻译过程中,发现的原文不妥处被更正。
3.    原文中许多内容一再重复,颇有蛇足之感,取精用宏,删繁就简。
4.    尝试更高程度的意译。

关键词

这个文章介绍主动对象模式,主动对象是内部拥有自己的控制线程的对象。为了简化异步调用的复杂性,这个模式分离了方法的执行和调用。使用这个模式, 一个对象中无论是否有独立的线程,客户从外部访问它时,感觉是一样的。生产者/消费者,读者/写者,这两个应用广泛的模型中,这种策略非常适合。这个模式 常用在多线程的,分布式系统中。另外,一些客户端应用,如:视窗系统和网络浏览器,也可以使用主动对象模式,对并行的、异步调起的IO操作简化处理。


1    目的
主动对象模式隔离了方法执行和方法调用的过程,提高了并行性,对内部拥有控制线程的主动对象,降低了异步访问的复杂 性。

2    别名
并行行为对象(Concurrent Object and Actor)

3    例子
为了说明主动对象模式,考虑一个通信网关的设计。网关隔离互相协作的多个组成单元,让交互过程不直接依赖于对方。参照图1, 一个分布式系统中,来自多个生产者(卫星设备)的消息,被网管转发给多个消费者(局域网内的主机)。

 
我们的例子中,生产者和消费者使用TCP协议通信,这是面向连接的通信协议。 网关上的进程向消费者发送数据时,操作会发生阻塞。这是因为,网络传输能力有限,TCP进行流量控制,防止过量的数据不能及时缓冲和处理。

要提高整体的效率,网关处理进程不能因一个连接上的阻塞而等待。另外,当生产者和消费者的数目增加的时候,整个进程必须相应的增加处理能力(译者 注:通过增加处理线程)。

一个提高性能的有效方法,就是使用并行。应用并行后,服务对象拥有独立线程,线程实际完成操作,和方法调用的过程分开。并且,不同线程处理不同 TCP连接,一个连接上的线程被阻塞,不会影响到其他连接的线程。

4    场景
对象的访问者(Client,下统称为客户)和对象的实现在不同的线程中。

5    问题
许多应用场景,服务者并行处理多客户端的请求,提高服务的质量(QoS)。被动对象在客户线程中完成操作过程,主动对象使用 专用的线程完成。一个对象的数据被多个线程共享时,必须处理好线程的同步。这导致三个约束。

1.    对一个对象调用不能阻塞整个进程,不能影响其他线程的执行:比如,通信网关的例子中,一个TCP连接上的数据传送被阻塞,整个进程仍然能继续处理。同样, 其他没有被阻塞的网络连接,应该正常的发送数据。
2.    对共享对象同步访问的逻辑应该简化:客户在使用共享对象地时候,如果面对底层的同步机制,必须记得先要获取互斥锁,后要释放互斥锁,编码就比较麻烦。一般 情况,共享对象的方法隐藏这些细节,当多个客户线程访问同一个对象时,这些约束是透明的。
3.    存在可以平行进行的操作,设计成同时执行:在通信网关的例子中,同时使用多个TCP连接给不同的消费者发送数据。如果网关的进程在单个线程上执行,及时使 用多个处理器不能明显的提高性能。

6    方案
对每一个要求并发执行的对象,分离其方法的调用和执行。这样,这个对象的客户就像是调用一个常规的方法一样。这个方法,自动 把任务交给另外的线程完成执行。

主动对象的组成:一个代理者(Proxy)实现外部的访问接口;一个执行者(Servant)。代理和执行者在不同的线程执行,分离方法调用和执行 的过程:代理者在客户线程中被调用执行,执行者在另外的线程完成操作。运行时,代理者把客户的调用信息封装“调用请求”(Method Request),通过调度者(Scheduler)把这个请求放到一个活动队列(Activation Queue)。调度者和执行者运行在另外的线程中,这个线程启动后,不断地从活动队列中得到“调用请求”对象,派发给执行者完成客户请求的操作。客户调用 代理者后马上得到一个预约容器(Future),今后可以通过这个预约容器得到返回的结果。

7    结构
下面使用Booch风格的类图,对主动对象的组成结构进行说明。(译者注:这是Booch在《面向对象的分析和设计》书中使 用的类图风格)

 

在这个模式中,共有六个参与者。
    代理者(Proxy)
    代理者定义了被客户调用的接口。这个接口是函数调用的方式,而不是像传统线程通信,使用数据传递的方式。当函数被调用的,代理者构造一个“调用请求”对 象,并把它放到活动队列中,这一切都发生在客户线程中。

    调用请求(Method Request)
    “调用请求”用来保存相关函数调用的部上下文信息,比如函数标识,函数的参数,这些信息将在不同线程间传递。一个抽象的“调用请求”类,定义了执行活动对 象方法的接口Call。并且包含一个Guard函数,Guard用来检查调用的条件是否满足。对代理者提供的每一个主动对象方法,在访问其执行者的时候需 要条件判断。代理者被调用的时候会创建具体“调用请求”对象,对象中包含了执行这个方法必须的参数和数据的返回方式。

    活动队列(Activation Queue)
    这个队列维护了一个缓冲区(译者注:不一定是先进先出的队列),缓冲区中存放了待执行的“调用请求”。正是这个队列分离可客户线程和执行操作的线程。

    调度者(Scheduler)
    调度者管理活动队列。调度者决定队列中的哪一个调用请求先被执行。调度的决定可能决定与多个规则:关键字顺序,入队的顺序,要满足的执行条件或等待发生的 事件,如:在一个数据结构中出现空闲区。调度者使用Guard方法的调用,来检查是否满足执行条件。

    执行者(Servant)
    真正完成操作的对象。执行者实际完成代理者定义的主动对象方法,响应一个“调用请求”。调度者给“调用请求”分派一共执行者,然后调用“调用请求”中的 Call方法。对应的执行者的方法将被调用。执行者的方法运行在调度者的线程中。执行者可能同时提供了一些方法供“调用请求”实现Guard。

    预约容器(Future)
    当执行者完成操作,客户通过预约容器获取返回结果。当客户调用代理者的方法后,一共空预约容器马上返回。预约容器指向一块内存空间,用来保存返回结果。客 户可以通过轮训或阻塞调用的方法,通过预约容器得到返回结果。

8    运行

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值