Java BlockingQueue take() 在 while 循环中
Java BlockingQueue take() in a while loop
我有一个 BlockingQueue,它由一个使用 put() 的线程填充。但是我对如何为 BlockingQueue 执行 take() 感到困惑。目前我是这样实现的:
String link;
try {
while(!(link = links.take()).isEmpty()) {
System.out.println(link);
}
} catch(InterruptedException ex) {
ex.printStackTrace();
}
是吗?如果不在条件语句中,如何循环队列并分配字符串变量?
我的理解是您在询问如何以一种好的方式终止 BlockingQueue。我能想到两种情况。在任何情况下,您都有消息生产者 A 和消息消费者 B。
- 消息生产者发送某种形式的终端值,如 "Stop"。您检查它,while 循环终止。
- 您可以中断消息生产者,这将在消费者端抛出 InterruptedException。这是避免终端输入情况的方法。这里的问题是,如果消费者实际上已经消费了队列中的所有内容,您将无法控制。所以中断通常在有条件要求消费立即终止时使用。
如果我没理解错的话,你问的是take
条件之外的方法?好吧,这并不难:
while (!links.isEmpty()) {
try {
String link = links.take();
// Do stuff.
} catch (InterruptedException e) {
// Exception handling.
}
}
您当前的条件 !(link = links.take()).isEmpty()
检查 return 值(字符串)是否为空(长度等于 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
is not necessary here, but it might become handy if you have multiple producers and/or consumers. It's also part of java.util.concurrent
你绝对应该检查一下。
我有一个 BlockingQueue,它由一个使用 put() 的线程填充。但是我对如何为 BlockingQueue 执行 take() 感到困惑。目前我是这样实现的:
String link;
try {
while(!(link = links.take()).isEmpty()) {
System.out.println(link);
}
} catch(InterruptedException ex) {
ex.printStackTrace();
}
是吗?如果不在条件语句中,如何循环队列并分配字符串变量?
我的理解是您在询问如何以一种好的方式终止 BlockingQueue。我能想到两种情况。在任何情况下,您都有消息生产者 A 和消息消费者 B。
- 消息生产者发送某种形式的终端值,如 "Stop"。您检查它,while 循环终止。
- 您可以中断消息生产者,这将在消费者端抛出 InterruptedException。这是避免终端输入情况的方法。这里的问题是,如果消费者实际上已经消费了队列中的所有内容,您将无法控制。所以中断通常在有条件要求消费立即终止时使用。
如果我没理解错的话,你问的是take
条件之外的方法?好吧,这并不难:
while (!links.isEmpty()) {
try {
String link = links.take();
// Do stuff.
} catch (InterruptedException e) {
// Exception handling.
}
}
您当前的条件 !(link = links.take()).isEmpty()
检查 return 值(字符串)是否为空(长度等于 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
is not necessary here, but it might become handy if you have multiple producers and/or consumers. It's also part of java.util.concurrent
你绝对应该检查一下。