实施" union"阻塞队列

时间:2016-12-11 07:21:38

标签: java java.util.concurrent

鉴于BlockingQueue<E>个实例的集合,在整个集合中实施阻止take()poll()的最有效方法是什么?这是代码:

class UnionBlockingQueue<E> implements BlockingQueue<E> {
  private final Collection<BlockingQueue<E>> sources;

  public UnionBlockingQueue(Collection<BlockingQueue<E>> sources) {
    this.sources = sources;
  }


  @Override
  public E take() throws InterruptedException {
    // takes first available E from the sources
  }

  @Override
  public E poll(long timeout, TimeUnit unit) throws InterruptedException {
    // polls first available E from the sources
  }

  // The rest is unsupported/irrelevant/out of scope
  @Override
  public boolean add(E e) {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean offer(E e) {
    throw new UnsupportedOperationException();
  }
}

我计划将每个源队列包装在一个单独的类中,该类将覆盖add / offer方法并触发此类的notFullnotEmpty条件,就像{的示例用法一样{3}},但是,作为Java队列的新手,我认为可能有更好/更安全/更有效的方法或已经存在的库。

1 个答案:

答案 0 :(得分:2)

最简单的方式是将子队列管道传输到SynchronousQueue

public static void main(String[] args) throws InterruptedException {

    // Input queues
    LinkedBlockingDeque<String> q1 = new LinkedBlockingDeque<>();
    LinkedBlockingDeque<String> q2 = new LinkedBlockingDeque<>();
    LinkedBlockingDeque<String> q3 = new LinkedBlockingDeque<>();
    List<LinkedBlockingDeque<String>> qs = Arrays.asList(q1, q2, q3);

    // Output queue
    SynchronousQueue<String> combined = new SynchronousQueue<>(true);

    // Pipe logic
    Executor executor = Executors.newCachedThreadPool(r -> {
        Thread t = new Thread(r, "q pipe");
        t.setDaemon(true);
        return t;
    });

    for (LinkedBlockingDeque<String> q : qs) {
        executor.execute(() -> {
            try {
                while (!Thread.currentThread().isInterrupted()) {
                    combined.put(q.take());
                }
            } catch (InterruptedException e) {
                // done
            }
        });
    }

    // Test
    q1.put("foo");
    q2.put("bar");
    q3.put("baz");

    String e;
    while ((e = combined.poll(100, TimeUnit.MILLISECONDS)) != null) {
        System.out.println(e);
    }
}