【问题标题】:producer-consumer: how to know inform that prodcution completed生产者-消费者:如何知道生产完成
【发布时间】:2011-09-06 05:12:40
【问题描述】:

我有以下情况:

  1. 从数据库中读取数据
  2. 做“计算”工作
  3. 将结果写入数据库

我有一个线程从数据库中读取数据并将生成的对象放入 BlockingQueue。这些对象非常重,因此队列限制了内存中的对象数量。 多个线程从队列中获取对象,执行工作并将结果放入第二个队列。 最后一个线程从第二个队列中获取结果并将结果保存到数据库中。

问题是如何防止死锁,例如。 “计算线程”需要知道何时不再有对象放入队列。 目前,我通过将线程的引用(可调用)相互传递并在轮询或提议之前检查 thread.isDone() 以及元素是否为空来实现这一点。我还检查了队列的大小,只要其中有元素,就必须消耗。使用 take 或 put 会导致死锁。

有没有更简单的方法来实现这一点?

【问题讨论】:

标签: java producer-consumer executorservice termination blockingqueue


【解决方案1】:

当您确定没有更多任务将到达队列时,其中一种方法是将“虚拟”或“毒药”消息作为队列中的最后一条消息放置..例如在放置之后与 db 查询的最后一行相关的消息。所以生产者在队列中放了一条虚拟消息,消费者收到这条虚拟消息后就知道这批不会有更多有意义的工作了。

【讨论】:

  • 我所拥有的更像是生产者-消费者/生产者-消费者模式。中间部分消费数据,然后将结果转发给另一个消费者。问题是我有这个“中间部分”的多个实例。这是完成艰苦工作的地方。问题是“虚拟数据”可以比之前的“真实数据”更快地通过这个链,因为没有对虚拟数据做任何工作。
  • 虚拟数据或位置信息只是为了避免死锁情况;所以你知道不会有更多的消息到达。您不妨使用倒计时锁或其他东西来跟踪已经开始的任务的完成情况。
【解决方案2】:

也许你应该看看CompletionService

它被设计成将执行器和队列功能合二为一。 完成执行的任务将通过

从完成服务中获得
completionServiceInstance.take() 

然后您可以再次为 3 使用另一个执行程序。即用结果填充 DB,您将使用从 completionServiceInstance 中获取的结果提供给它。

【讨论】:

  • 这对我没有帮助,因为我没有传递大量任务,而是从数据库生成的对象。我只有 3 个必须并行运行的任务 1. 从数据库读取 2. 工作 3. 将结果写入数据库。它们必须并行以限制内存使用,因为读取和写入比实际工作要快得多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-26
  • 2013-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多