【问题标题】:Java BlockingQueue cause threads wait unnecessarily.Java BlockingQueue 导致线程不必要地等待。
【发布时间】:2013-05-17 16:51:45
【问题描述】:

我正在使用 BlockingQueue(LinkedBlockingQueue) 在多个线程之间同步数据。请看下面的图片。

主线程是一个生产者,它生产对象,然后将它们放入每个消费者的队列中(线程2-10)。需要强调的是,每个消费者都有自己的队列,并且每个产生的对象都会进入所有消费者的队列。

生产者的运行速度比消费者快得多,因此我们可以假设在消费者运行期间队列不应为空。当任何消费者的队列达到其容量时,生产者将被阻止(生产者使用put())。消费者使用take()从队列中取出对象。

使用此设置,我会假设消费者很少(如果可能的话)在队列为空时等待。但是,从我附在下面的图片中,我可以看到,有时,所有消费者都必须在队列中等待被对象填充;在等待期间,我可以看到生产者正在运行。

这不是我对BlockingQueue的理解,我以为只要生产者生产东西并放入队列,消费者就应该开始工作。为什么消费者线程有这么长的等待时间超出了我的理解。

有人可以解释一下吗?有没有简单的方法来分析这类应用程序?

【问题讨论】:

  • 您是否尝试过使用包装队列和线程池的 ExecutorService?与使用现有库相比,您的系统有哪些优势?
  • 和ExecutorService的框架有点不同。每个产生的对象都需要被所有的消费者线程处理。在 ExecutorService 中,只有一名工作人员会处理提交的作业。我愿意看看是否有任何调整 ExecutorService 以适应这种设计,但我还没有找到解决方案。
  • 这是因为每个线程根据该对象执行不同的工作吗?您是否查看过 Disruptor 库,因为它旨在成为您尝试做的更高性能的版本。即将每个事件的工作拆分到多个线程中。
  • 我的回答有帮助吗?如果是,请投票和/或接受。

标签: java concurrency java.util.concurrent


【解决方案1】:

这不是我对BlockingQueue的理解,我以为只要生产者生产东西并放入队列,消费者就应该开始工作。为什么消费者线程有这么长的等待时间,我无法理解。

这很可能不是BlockingQueue 的问题。

  1. 您可能不正确,生产者落后于消费者。也许生产者正在爆发,有时正在从加载的磁盘中读取并落后。

  2. 也许消费者正在阻止某个 other 对象,而不是 BlockingQueue。消费者在用这些数据做什么?他们是将其写入磁盘还是通过网络发送?他们执行的任何其他可以阻止的操作?

  3. 另一种可能性是只有几个线程跟上生产者的步伐,因此许多线程正在按 LIFO 线程顺序等待。换句话说,如果一个线程刚刚完成,它可能会采用生产者添加的最新元素。因此,有几个线程保持忙碌,而其他线程则更多地处于阻塞状态。我不确定您的队列是否是这样实现的。

有没有简单的方法来分析这类应用程序?

要做的一件事是查看堆栈跟踪以查看每个线程在何处被阻塞。如果您的线程实际上正在等待阻塞队列,这将使您更好地了解。您可以使用 jconsole 实时查看线程或每隔一段时间发送一个QUIT 信号。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-17
    • 2015-07-04
    相关资源
    最近更新 更多