回顾:
并发型模式有
主动对象模式(Active Object)。
阻碍模式(Balking)。
双重检查锁定(Double Checked Locking)。
守卫模式(Guarded)。
领导者/追随者模式(Leaders/Followers)。
监测对象模式(Monitor object)。
读写锁模式(Read write lock)。
调度模式(Scheduler)。
1.什么是主动对象?
别名:并行行为对象(ConcurrentObjectandActor)
对象分为主动对象和被动对象,主动对象内部包含一个线程,可以自动完成动作或改变状态,而一般的被动对象只能通过被其他对象调用才有所作为。在多线程程序中,经常把一个线程封装到主动对象里面。主动对象是内部拥有自己的控制线程的对象,这个模式分离了方法的执行和调用。
2.怎么理解执行和调用分离?
主动对象模式中的“执行”和“调用”分离可以理解为以下两个方面:
-
方法执行与调用者的分离:在主动对象模式中,方法的执行并不依赖于特定的调用者。相反,方法被封装在对象内部,并由对象自己的控制线程负责执行。这种设计使得方法的执行与调用者之间解耦,使得不同的调用者可以以不同的方式访问和操作同一个对象,而不会相互影响。
-
并发执行与同步控制的分离:主动对象模式中的对象拥有自己的控制线程,可以并发地执行多个操作。为了实现并发执行,对象的内部状态被封装在对象自身中,并且通过同步机制来保护对对象的并发访问。这种设计将并发执行与同步控制分离,使得对象的访问可以在不同的线程中并发进行,提高了系统的并发性能和响应能力。
通过以上两个方面的分离,主动对象模式实现了方法执行与调用者的解耦以及并发执行与同步控制的解耦。这种设计简化了对象的访问方式,提高了系统的可扩展性和灵活性。
假设我们有一个餐厅,餐厅里有不同的厨师,可以为不同的客人制作不同的菜品。
- 方法执行与调用者的分离:在这个例子中,厨师是对象的内部执行者,他们负责在厨房里制作菜品。客人是调用者,他们通过点餐来请求厨师制作菜品。厨师并不直接与客人交互,而是通过订单来接收客人的请求,并执行相应的操作。这种设计使得厨师的执行与客人的调用解耦,客人可以随时点餐而不必关心厨师的工作细节。
- 并发执行与同步控制的分离:在餐厅中,多个厨师可以同时为不同的客人制作菜品。为了协调这种并发访问,餐厅需要一个调度员(或称同步控制者)来管理厨师的工作,避免不同客人的菜品相互干扰。这个调度员就是对象的控制线程,它负责协调多个厨师的工作,保证每个客人的菜品可以正确地制作完成。这种设计将并发的执行与同步控制分离,使得餐厅可以高效地服务多个客人。
通过这个例子,我们可以看到主动对象模式在生活中无处不在。通过将执行与调用者分离以及并发执行与同步控制的分离,主动对象模式提高了系统的可扩展性和灵活性。
3.组成结构
在这个模式中,共有六个参与者。
代理者(Proxy)(服务员)
代理者定义了被客户调用的接口。这个接口是函数调用的方式,而不是像传统线程通信,使用数据传递的方式。当函数被调用的,代理者构造一个“调用请求”对象,并把它放到活动队列中,这一切都发生在客户线程中。
调用请求(MethodRequest)(这里应该顾客,顾客点餐)
“调用请求”用来保存相关函数调用的部上下文信息,比如函数标识,函数的参数,这些信息将在不同线程间传递。一个抽象的“调用请求”类,定义了执行活动对象方法的接口Call。并且包含一个Guard函数,Guard用来检查调用的条件是否满足。对代理者提供的每一个主动对象方法,在访问其执行者的时候需要条件判断。代理者被调用的时候会创建具体“调用请求”对象,对象中包含了执行这个方法必须的参数和数据的返回方式。
活动队列(ActivationQueue)(厨房烹饪清单)
这个队列维护了一个缓冲区(译者注:不一定是先进先出的队列),缓冲区中存放了待执行的“调用请求”。正是这个队列分离可客户线程和执行操作的线程。
调度者(Scheduler)(主厨/厨师长)
调度者管理活动队列。调度者决定队列中的哪一个调用请求先被执行。调度的决定可能决定与多个规则:关键字顺序,入队的顺序,要满足的执行条件或等待发生的事件,如:在一个数据结构中出现空闲区。调度者使用Guard方法的调用,来检查是否满足执行条件。
执行者(Servant)(厨师)
真正完成操作的对象。执行者实际完成代理者定义的主动对象方法,响应一个“调用请求”。调度者给“调用请求”分派一共执行者,然后调用“调用请求”中的Call方法。对应的执行者的方法将被调用。执行者的方法运行在调度者的线程中。执行者可能同时提供了一些方法供“调用请求”实现Guard。
预约容器(Future)(菜品)
当执行者完成操作,客户通过预约容器获取返回结果。当客户调用代理者的方法后,一共空预约容器马上返回。预约容器指向一块内存空间,用来保存返回结果。客户可以通过轮训或阻塞调用的方法,通过预约容器得到返回结果。
4.使用场景
主动对象模式是一种并发编程的设计模式,其使用场景适合于需要多线程服务且分布式系统中。
具体来说,主动对象模式适合以下情况:
- 生产者/消费者模型:该模式非常适合生产者/消费者模型,特别是当生产者和消费者在两个不同的线程中运行时。通过使用主动对象模式,可以很容易地实现线程间的安全协调。
- 读者/作者模型:该模式也可用于读者/作者模型,允许多个读者和作者独立地访问共享资源,并保证访问的同步性。
- 异步和并行的网络操作:对于需要进行异步和并行网络操作的客户端应用,如视窗系统和网络浏览器,主动对象模式可以简化对并行的、异步调起的IO操作的处理。
此外,主动对象模式还可以用于需要对耗时的任务进行分解,以减少主线程等待时间的情况。
总的来说,主动对象模式的主要优点是能够提高系统的并发性,从而提高系统的吞吐率,适合于需要进行多线程处理和并发访问同一资源的场景。但是这种模式也需要考虑到可能出现的问题,比如线程间的竞争和同步问题。
课后习题:
以TCP网络服务为例,以主动对象模式的思路完成代码实现。