简体   繁体   English

多个阻塞队列,单个消费者

[英]Multiple blocking queues, single consumer

I have multiple BlockingQueues containing messages to be sent. 我有多个BlockingQueues包含要发送的消息。 Is it possible to have fewer consumers than queues? 是否可以减少消费者而不是队列? I don't want to loop over the queues and keep polling them (busy waiting) and I don't want a thread for every queue. 我不想循环遍历队列并继续轮询它们(忙等待)并且我不希望每个队列都有一个线程。 Instead, I would like to have one thread that is awoken when a message is available on any of the queues. 相反,我希望有一个线程在任何队列上有消息时被唤醒。

The LinkedBlockingMultiQueue does what you are asking for. LinkedBlockingMultiQueue可以满足您的要求。 It does not allow the consumer to block on arbitrary BlockingQueues, but it is possible to create "sub queues" from a single "multi queue" and achieve the same effect. 它不允许消费者阻止任意BlockingQueues,但可以从单个“多队列”创建“子队列”并实现相同的效果。 Producers offer in the sub queues, and consumers can block themselves polling the single multi queue, waiting for any element. 生产者提供子队列,消费者可以阻止自己轮询单个多队列,等待任何元素。

It also supports priorities, that is, taking elements from some queues before considering others. 它还支持优先级,即在考虑其他队列之前从某些队列中获取元素。

Example: 例:

LinkedBlockingMultiQueue<Int, String> q = new LinkedBlockingMultiQueue<>();
q.addSubQueue(1 /* key */, 10 /* priority */);
q.addSubQueue(2 /* key */, 10 /* priority */);
LinkedBlockingMultiQueue<Int, String>.SubQueue sq1 = q.getSubQueue(1);
LinkedBlockingMultiQueue<Int, String>.SubQueue sq2 = q.getSubQueue(2);

Then you can offer and poll: 然后你可以提供和投票:

sq1.offer("x1");
q.poll(); // "x1"
sq2.offer("x2");
q.poll(); // "x2"

Disclaimer: I am the author of the library. 免责声明:我是图书馆的作者。

One trick that you could do is to have a queue of queues. 您可以做的一个技巧是拥有一个队列队列。 So what you'd do is have a single blocking queue which all threads subscribe to. 所以你要做的是拥有一个所有线程都订阅的阻塞队列。 Then when you enqueue something into one of your BlockingQueues, you also enqueue your blocking queue on this single queue. 然后,当您将某些内容排入某个BlockingQueues时,您还会在此单个队列中将阻塞队列排入队列。 So you would have something like: 所以你会有类似的东西:

BlockingQueue<WorkItem> producers[] = new BlockingQueue<WorkItem>[NUM_PRODUCERS];
BlockingQueue<BlockingQueue<WorkItem>> producerProducer = new BlockingQueue<BlockingQueue<WorkItem>>();

Then when you get a new work item: 然后当你得到一个新的工作项:

void addWorkItem(int queueIndex, WorkItem workItem) {
    assert queueIndex >= 0 && queueIndex < NUM_PRODUCERS : "Pick a valid number";
    //Note: You may want to make the two operations a single atomic operation
    producers[queueIndex].add(workItem);
    producerProducer.add(producers[queueIndex]);
}

Now your consumers can all block on the producerProducer. 现在您的消费者可以全部阻止producerProducer。 I am not sure how valuable this strategy would be, but it does accomplish what you want. 我不确定这种策略会有多么有价值,但它确实能达到你想要的效果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM