3

我有一个线程在一个循环中做两件事:等待来自 BlockingQueue 的对象,然后处理它们。处理逻辑具有可在 JVM 之外观察到的效果,并且必须以原子方式完成。

目前,该线程由 volatile 布尔变量控制,如https://stackoverflow.com/a/10961760/499922中所述。但是,这意味着如果队列中没有更多消息可供线程使用,线程将不会停止。'Thread.interrupt()` 不能用来解决这个问题,因为它可以中途中断原子操作。

有没有办法只中断take()队列上的方法而不是任何其他操作?

4

4 回答 4

2

'Thread.interrupt()` 不能用来解决这个问题,因为它可以中途中断原子操作。

它不这样做。它所做的只是设置一个标志,这与设置易失性字段非常相似。

即使您要使用Thread.stop()已弃用并且可以触发任何代码行抛出错误的代码,您仍然可以捕获此类错误并确保您的数据处于一致状态。

我不会创建队列和线程来执行该队列之外的任务,而是使用具有这两者的 ExecutorService ,它可用于取消/中断单个任务,支持多个线程,正常或立即关闭并等待终止。

很有可能你最好不要重新发明这个轮子。;)

于 2013-01-03T19:41:17.470 回答
1

一种方法是在队列中放置一个特殊的“哨兵”对象。线程会知道这个特殊对象的含义,并在收到它时采取适当的行动。

于 2013-01-03T19:32:47.737 回答
1

我发现在这种情况下最好的方法是使用“毒丸”——你在队列中放置一个对象,该对象仅用于切换某个动作。

它在实践中的 Java 并发中得到了广泛的介绍(​​我的副本中的第 155 页,第 7.2.3 页)。有关该部分的程序示例,请参见此处。

于 2013-01-03T19:33:24.547 回答
0

与其依赖 volatile 布尔值,不如依赖线程的中断标志:

while (!Thread.currentThread().isInterrupted()) {
    try {
        Object value = queue.take();
        handle(value);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}

这样,当流被阻塞时,take()它会在线程中断时立即退出循环。如果它在任何其他时间被中断,它将在完成当前循环后退出循环。

或者,您可以将其编码为在中断后继续循环,只要对象立即在队列中可用,poll()从那时起使用。

于 2013-01-03T19:33:25.233 回答