我有多个BlockingQueues包含要发送的消息。是否可以减少消费者而不是队列?我不想循环遍历队列并继续轮询它们(忙等待)并且我不希望每个队列都有一个线程。相反,我希望有一个线程在任何队列上都有消息时被唤醒。
答案 0 :(得分:6)
您可以做的一个技巧是拥有一个队列队列。所以你要做的是拥有一个所有线程都订阅的阻塞队列。然后,当您将某些内容排入某个BlockingQueues时,您还会在此单个队列中将阻塞队列排入队列。所以你会有类似的东西:
BlockingQueue<WorkItem> producers[] = new BlockingQueue<WorkItem>[NUM_PRODUCERS];
BlockingQueue<BlockingQueue<WorkItem>> producerProducer = new BlockingQueue<BlockingQueue<WorkItem>>();
然后当你得到一个新的工作项目时:
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]);
}
现在您的消费者可以全部阻止producerProducer。我不确定这种策略有多么有价值,但它确实能达到你想要的效果。
答案 1 :(得分:6)
LinkedBlockingMultiQueue符合您的要求。它不允许消费者阻止任意BlockingQueues,但是可以创建&#34;子队列&#34;来自单个&#34;多队列&#34;并达到同样的效果。生产者提供子队列,消费者可以阻止自己轮询单个多队列,等待任何元素。
它还支持优先级,即在考虑其他队列之前从某些队列中获取元素。
示例:
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);
然后你可以提供和投票:
sq1.offer("x1");
q.poll(); // "x1"
sq2.offer("x2");
q.poll(); // "x2"
免责声明:我是图书馆的作者。
答案 2 :(得分:0)
这可以使用多态性解决,假设您有两个分别称为JobOne
和JobTwo
的工作,并且您将由消费者使用它们。您应该定义一个称为Jobs的接口,例如:
interface Jobs {
...
}
然后您可以通过以下界面来实现您的工作:
class JobOne implements Job {
...
}
class JobTwo implements Job {
...
}
现在,您可以将Jobs
用于阻塞队列以添加两种要使用的作业。
BlockingQueue<Jobs> Jobs queue = new BlockingQueue<Jobs>();