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

时间:2012-03-06 16:55:38

标签: java concurrency

我有多个BlockingQueues包含要发送的消息。是否可以减少消费者而不是队列?我不想循环遍历队列并继续轮询它们(忙等待)并且我不希望每个队列都有一个线程。相反,我希望有一个线程在任何队列上都有消息时被唤醒。

3 个答案:

答案 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)

多态

这可以使用多态性解决,假设您有两个分别称为JobOneJobTwo的工作,并且您将由消费者使用它们。您应该定义一个称为Jobs的接口,例如:

interface Jobs {
    ...
}

然后您可以通过以下界面来实现您的工作:

class JobOne implements Job {
    ...
}

class JobTwo implements Job {
    ...
}

现在,您可以将Jobs用于阻塞队列以添加两种要使用的作业。

BlockingQueue<Jobs> Jobs queue = new BlockingQueue<Jobs>();