鉴于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方法并触发此类的notFull
和notEmpty
条件,就像{的示例用法一样{3}},但是,作为Java队列的新手,我认为可能有更好/更安全/更有效的方法或已经存在的库。
答案 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);
}
}