Worker Thread模式

Worker Thread模式名称的来源是工厂的工作流程。工人的数目是固定的,每个工人会独立获取任务进行工作,完成自己的工作后再获取新的工作,如果没有新的工作,就等待工作的到来。我们可以用工作线程来建模工人,用一个带有同步控制的Channel类来建模工人获取工作的地方。因为可用的工作线程的数目是确定的,这种模式也称为线程池模式。我们可以发现,Worker Thread模式和之前的Thread Per Message有很大的相似之处,Worker Thread模式中工作线程的数目是实现确定的,这些工作线程也一般是在开始就初始化好的;而之前提到的模式中,每有一项新任务到达,会创建一个新的进程,工作完成之后,创建的进程就会停止。具体哪种模式更好,取决于具体的场景。除了Thread Per Message模式,我们可以发现,Worker Thread模式中关键的Channel类和生产者消费者模式中的Channel的控制方式几乎相同,准确的说,Worker Thread就是使用生产者消费者模式进行工作的提交与获取。

综上所述,Worker Thread模式其实是Thread Per Message模式和生产者消费者模式的结合。它完善了Thread Per Message模式中每项任务都需要创建新线程的缺点,而是事先创建好固定数量的线程,然后用生产者消费者模式来向线程池分配任务。Worker Thread模式和Thread Per Message都实现了调用者(invoker)和执行者(executor)的分离,有利于提高程序的响应速度。

Future模式

与Worker Thread模式有些类似的是,Future模式也是对Thread Per Message模式的改进。我们在讲解Thread Per Message模式时提到,它的一个缺点是无法获取返回值,因为方法在调用之后就立刻返回了,具体的执行会交给一个新的线程,在返回时任务还在执行中,因此无法获取返回值。但如果我们要执行的任务是像计算任务这样关键点在于结果(返回值),我们要如何获取在将来(future)才能计算得到的结果呢?

其实仔细一想,这个问题并不难解决。我们可以在调用时(invoke)返回一个类似“凭证”的对象,在之后需要返回值的时候通过该对象的方法来检测工作是否完成,如果完成就返回相应的结果。

思路的关键在于分离。之前的Thread Per Message完成了调用者(invoker)和执行者(executor)的分离,Future模式则完成了执行与返回的分离。我们并不一定要在执行完后立即返回结果,只要把结果保存好,需要的时候通过“凭证”获取即可。当然类似于观察者模式中推和拉获取消息的不同,之前提到的凭证方式其实是一种式获取返回值的方法,我们完全也可以采用式,学习JavaScript等语言中的回调(callback)方式,在调用时(invoke)传给工作线程一个可以回调的函数,工作线程完成任务之后,通过回调函数返回并记录结果即可。