繁体   English   中英

Java BlockingQueue在while循环中使用take()

[英]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();
}

是对的吗? 如果不在条件语句中,如何循环队列并分配字符串变量?

如果我理解正确的,你问的方式来take的条件之外? 嗯,这并不难:

while (!links.isEmpty()) {
    try {
        String link = links.take();
        // Do stuff.
    } catch (InterruptedException e) {
        // Exception handling.
    }
}

您当前的状况!(link = links.take()).isEmpty()检查返回值 - 字符串 - 是否为空(长度等于0),而不是队列。

无论如何,请记住上面的代码不是原子的 ,所以不能保证在links.isEmpty()links.take()之间不会发生任何其他事情。

编辑:您可以在启动期间使用标志处理竞争条件

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的一部分。

我的理解是你问的是如何以一种好的方式终止BlockingQueue。 我能想到两种情况。 在任何情况下,您都有一个消息生成器A和消息使用者B.

  1. 消息生产者发送某种形式的终端值,如“停止”。 您检查它并且while循环终止。
  2. 您可以中断消息生成器,它将在消费者端抛出InterruptedException。 这是避免终端输入情况的方法。 这里的问题是,如果消费者实际上已经消耗了队列中的所有内容,那么你就无法控制。 因此,如果存在需要消耗以立即终止的条件,则通常使用中断。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM