多个阻塞队列,单个使用者

2022-09-02 04:20:31

我有多个阻止队列,其中包含要发送的消息。是否有可能拥有比队列更少的使用者?我不想循环队列并继续轮询它们(忙于等待),我不想为每个队列都有一个线程。相反,我希望有一个线程在任何队列上都有可用消息时被唤醒。


答案 1

LinkedBlockingMultiQueue可以满足您的要求。它不允许消费者在任意BlocktingQueues上阻塞,但是可以从单个“多队列”创建“子队列”并达到相同的效果。生产者在子队列中提供,消费者可以阻止自己轮询单个多队列,等待任何元素。

它还支持优先级,即在考虑其他队列之前从某些队列中获取元素。

例:

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

你可以做的一个技巧是有一个队列队列。所以你要做的是有一个所有线程都订阅的单个阻塞队列。然后,当您将某些内容排队到其中一个阻塞队列中时,您还会将阻塞队列排队到此单个队列上。所以你会有这样的东西:

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]);
}

现在,您的消费者都可以在生产者生产者上阻止。我不确定这种策略有多大价值,但它确实实现了你想要的。


推荐