【问题标题】:How do I give priority to Consumers when using a LinkedBlockingQueue?使用 LinkedBlockingQueue 时如何优先考虑消费者?
【发布时间】:2013-07-19 14:11:51
【问题描述】:

我正在使用 LinkedBlockingQueue 和生产者/消费者模式来缓冲任务。要将任务添加到队列中,我使用生产者的方法:Queue.put(Object);要从我用于消费者的队列中获取任务:Queue.take(Object);

我在 Java api 中发现这两种方法都会阻塞,直到队列可用。我的问题是:我知道在我的系统中有更多的任务生产者而不是消费者。我所有的任务都需要处理。所以我需要我的消费者在被阻塞时优先于生产者来获取队列。

他们有办法做到这一点而无需过多地改变 LinkedBlockingQueue 的方法吗?

【问题讨论】:

  • 据我所知,这个队列在设计上不会阻塞消费者,即使生产者由于队列已满而被阻塞。

标签: java concurrency


【解决方案1】:

LinkedBlockingQueue 使用两个 ReenterantLocks 锁。

private final ReentrantLock putLock = new ReentrantLock();

private final ReentrantLock takeLock = new ReentrantLock();

由于这两个锁是独立的,并且 put 和 take 获取单独的锁以执行它们的操作,因此阻塞一个操作不会影响其他操作。

干杯!!

【讨论】:

  • 所以生产者和消费者可以同时访问队列?!好的,谢谢你的快速回答!
  • 是的!但是,还有某些其他操作会完全锁定队列以进行读取和写入。例如如果你调用 toArray 或 clear 方法。
【解决方案2】:

没有必要将消费者优先于生产者,因为它们在完全不同的条件下阻塞:如果生产者因为队列已满而被阻塞,那么消费者不会因为队列为空而被阻塞。

例如,producer1 有一个阻塞的put 调用,因为队列已满。 Consumer1 然后执行take,因为队列不为空(除非您的队列容量为 0,这将是愚蠢的) - 消费者不知道或不关心生产者的 put 调用被阻塞,它只关心队列不为空。

【讨论】:

    【解决方案3】:

    由于多个独立的锁,被阻塞的生产者不会阻塞消费者。

    take( 状态:

    检索并移除此队列的头部,如有必要,等待元素可用。

    put( 状态:

    在此队列的尾部插入指定元素,如有必要,等待空间可用

    如果没有空间,那么 put 将阻塞但 take 不会被阻塞,因为它的设计只有在队列为空时才等待,显然这里不是这种情况。


    原评论:

    据我所知,即使生产者由于队列已满而被阻塞,这个队列在设计上也不会阻塞消费者。

    【讨论】:

      猜你喜欢
      • 2020-04-20
      • 1970-01-01
      • 2021-03-18
      • 1970-01-01
      • 2021-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-25
      相关资源
      最近更新 更多