如何并行等待多个阻塞队列?

时间:2016-03-31 10:20:24

标签: java concurrency blockingqueue

我有两个独立的阻塞队列。客户端通常使用第二个阻塞队列中的第一个来检索要处理的元素。

在某些情况下,客户端对两个阻塞队列中的元素感兴趣,无论哪个队列首先提供数据。

客户端如何同时等待两个队列?

3 个答案:

答案 0 :(得分:2)

您可以尝试在某种循环中使用poll方法,只在一个队列中等待指定的时间,然后再轮询另一个队列。

除此之外,我会说在不同的线程上为每个队列运行阻塞操作,并为主应用程序提供回调接口是另一个稍微复杂的选项。

答案 1 :(得分:1)

我遇到了同样的问题,最后编写了自己的并发队列来支持这种使用模式。

由于Java阻塞原语不允许阻塞多个对象,因此解决方案被推送到集合本身:Linked Blocking Multi Queue实际上是由头连接的一组队列。元素提供给单个“子队列”,但从单个位置检索(支持阻塞操作)。

答案 2 :(得分:0)

我会创建某种聚合队列,将操作委托给真实队列:

class AggregatedQueue<E> /*implements Queue<E>*/ {
    final List<BlockingQueue<E>> queues;
    final ExecutorService service;

    final AtomicBoolean shutdown = new AtomicBoolean(false);
    final BlockingQueue<E> aggregatedQueue = new LinkedBlockingQueue<>();

    public AggregatedQueue(List<BlockingQueue<E>> queues) {
        this.queues = queues;
        this.service = Executors.newFixedThreadPool(queues.size());
    }

    public void start() {
        for (BlockingQueue<E> queue : queues) {
            service.submit((Runnable) () -> {
                while (!shutdown.get()) {
                    try {
                        aggregatedQueue.add(queue.take());
                    } catch (InterruptedException e) {
                        // handle
                    }
                }
            });
        }
    }

    //@Override
    public E take() throws InterruptedException {
        return aggregatedQueue.take();
    }
}

要使用它,您应该在构造函数中传递队列并调用start方法。将有1个线程侦听每个队列并将获取的元素传递给聚合队列。

AggregatedQueue<Message> queue = new AggregatedQueue<>(Arrays.asList(q1, q2));
queue.start();
while (listening) {
    Message msg = queue.take();
    dispatch(msg);
}
queue.shutdown();