消费者/生产者与观察者/可观察者之间的差异


15

我正在设计一个包含三个部分的应用程序:

  • 监视某些事件(文件创建,外部请求等)发生的单个线程
  • N个工作线程通过处理它们来响应这些事件(每个工作进程处理并消耗一个事件,并且处理可能需要花费可变的时间)
  • 一个控制器,用于管理那些线程并执行错误处理(线程重新启动,结果记录)

尽管这是非常基本的,并且不难实现,但我想知道这样做的“正确”方法是什么(在Java的这种具体情况下,但也希望有更高的抽象答案)。我想到两种策略:

  • 观察者/可观察者:监视线程由控制器观察。在发生事件的情况下,然后会通知控制器,并可以将新任务分配给可重用的缓存线程池中的空闲线程(如果所有线程当前都忙,请等待并将任务缓存在FIFO队列中)。工作线程实现Callable并返回结果(或布尔值)成功或返回错误,在这种情况下,控制器可以决定要执行的操作(取决于发生的错误的性质)。

  • 生产者/消费者:监视线程与控制器(事件队列)共享一个BlockingQueue,并且控制器与所有工作器(任务队列和结果队列)共享两个。在发生事件的情况下,监视线程将任务对象放入事件队列中。控制器从事件队列中获取新任务,对其进行审阅并将其放入任务队列中。每个工作人员都在等待新任务,并从任务队列中获取/使用它们(先到先服务,由队列本身进行管理),然后将结果或错误放回到结果队列中。最后,控制器可以从结果队列中检索结果,并在出现错误的情况下采取相应的步骤。

两种方法的最终结果是相似的,但是它们都有细微的差别:

使用观察者,线程的控制是直接的,每个任务都归属于特定的新生成的工作程序。创建线程的开销可能更高,但是由于缓存了线程池,因此开销并不大。另一方面,“观察者”模式被简化为单个“观察者”模式,而不是多个观察者模式,这与其设计的目的不完全相同。

队列策略似乎更容易扩展,例如,添加多个生产者而不是一个生产者很简单,不需要任何更改。不利之处在于,即使根本不做任何工作,所有线程也将无限期运行,并且错误/结果处理看起来不像第一个解决方案那样优雅。

在这种情况下最合适的方法是什么?为什么?我发现很难在线找到该问题的答案,因为大多数示例仅处理明确的案例,例如用“观察者”案例更新许多具有新值的窗口或与多个消费者和生产者进行处理。任何输入,不胜感激。

Answers:


10

您即将回答自己的问题。:)

在“可观察/观察者”模式(请注意翻转)中,需要牢记三件事:

  1. 通常,可观察到更改的通知,即“有效负载”。
  2. 可观察的存在
  3. 现有的可观察对象必须知道观察者(否则就没有观察对象了)。

通过组合这些点,隐含的是可观察者知道其下游组成部分,即观察者是什么。数据流本质上是由可观察的驱动的-观察者只是根据他们所观察的东西“生死存亡”。

在生产者/消费者模式中,您将获得非常不同的交互:

  1. 通常,有效载荷独立于负责生产有效载荷的生产者而存在。
  2. 生产者不知道消费者如何或何时活跃。
  3. 消费者不需要知道有效载荷的生产者。

现在,生产者和消费者之间的数据流已完全切断-生产者知道的只有它具有输出,而所有消费者知道的只有它具有输入。重要的是,这意味着生产者和消费者可以完全不存在对方而存在。

另一个不太细微的差异是,同一可观察对象上的多个观察者通常会获得相同的有效负载(除非有非常规的实现),而同一生产者之外的多个使用者可能不会。这取决于中介是队列方式还是主题方式。前者为每个消费者传递不同的消息,而后者则确保(或尝试)所有消费者均基于每个消息进行处理。

使它们适合您的应用程序:

  • 在Observable / Observer模式中,每当您的监视线程正在初始化时,它都必须知道如何通知控制器。作为观察者,控制器可能要先等待来自监视线程的通知,然后才能让线程处理更改。
  • 在生产者/消费者模式中,您的监视线程只需要知道事件队列的存在,并与之交互即可。作为使用者,控制器然后轮询事件队列,并在获得新的有效负载后,让线程对其进行处理。

因此,直接回答您的问题:如果要在监视线程和控制器之间保持一定程度的分离,以便可以独立操作它们,则应采用“生产者/消费者”模式。


2
感谢您的详细回答。不幸的是,由于缺少声誉,我无法对其进行投票,因此我将其标记为一种解决方案。到目前为止,您提到的两个部分之间的时间独立性是积极的。队列可以管理许多事件的短时间突发,并具有较长的暂停时间,这比观察到事件后的直接操作要好得多(如果最大线程数是固定的并且相对较低)。线程数也可以根据当前队列项目数动态增加/减少。
user183536

@ user183536没问题,很高兴为您提供帮助!:)
hjk 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.