我有一个BlockingQueue,它由一个带有put()的线程填充。但我对如何为BlockingQueue执行take()感到困惑。目前我用这种方式实现了它:
String link;
try {
while(!(link = links.take()).isEmpty()) {
System.out.println(link);
}
} catch(InterruptedException ex) {
ex.printStackTrace();
}
是吗?如果不在条件语句中,如何循环队列并分配字符串变量?
答案 0 :(得分:1)
我的理解是,您正在询问如何以良好的方式终止BlockingQueue。我能想到两种情况。在任何情况下,您都有消息生成器A和消息使用者B.
答案 1 :(得分:1)
如果我理解正确,你已经要求在条件之外找到take
的方法吗?嗯,这并不难:
while (!links.isEmpty()) {
try {
String link = links.take();
// Do stuff.
} catch (InterruptedException e) {
// Exception handling.
}
}
您当前的条件!(link = links.take()).isEmpty()
检查返回值 - 字符串 - 是否为空(长度等于0),而不是队列。
无论如何,请注意上面的代码不是atomic,因此无法保证在links.isEmpty()
和links.take()
之间不会发生其他任何事情。
编辑:您可以在启动期间使用标记处理race conditions:
BlockingQueue<Integer> numbers = new ArrayBlockingQueue<>(10);
AtomicBoolean flag = new AtomicBoolean(true);
// Producer.
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
numbers.put(i);
} catch (InterruptedException e) { /* NOP */ }
}
flag.set(false);
}).start();
// Consumer.
while (flag.get() || !numbers.isEmpty()) {
try {
System.out.println(numbers.take());
} catch (InterruptedException e) { /* NOP */ }
}
此处不需要AtomicBoolean
,但如果您有多个生产者和/或消费者,它可能会变得很方便。它也是java.util.concurrent
的一部分你绝对应该结帐。