0

我正在使用LinkedBlockingQueue默认情况下用于消费者的 RabbitMQ。它有一个阻塞nextDelivery()方法,基本上调用take()队列。

但如果它在调用该方法之前被中断,它不会捕获中断。

if (Thread.interrupted()) {
    throw new InterruptedException();
}
// If interrupted here, call below will not throw interrupted exception
rabbit.nextDelivery();

它仅在等待时发生中断时才有效 - 这也是 javadoc 中所写的 - 或者如果先阻塞则命中。

Throws:
    InterruptedException - if interrupted while waiting

我实际上有一个案例,中断恰好在我标记的地方命中。如果我在开始或中间开始睡眠,它会起作用,但假设它总是会起作用仍然不安全。

是否有替代 BlockingQueue 实现解决了这个问题?我不知道它是否消耗了中断,也许静态方法中存在竞争条件它返回false但以某种方式清除设置值?

编辑:这与Thread.interrupted()呼叫或不设置标志无关。如果你注释掉 if block,它又是同样的问题。队列方法一进入就不会抛出InterruptedException,它只是阻塞

4

1 回答 1

3

但如果它在调用该方法之前被中断,它不会捕获中断。

因此,如果我理解您的问题,那么某些东西正在吞噬InterruptedException或清除中断标志。以下代码总是InterruptedException为我抛出。

Thread.currentThread().interrupt();
new LinkedBlockingQueue<String>().take();

重要的是要意识到当InterruptException抛出 时,中断标志被清除。您应该始终执行以下操作:

try {
    // other methods where this is needed are Object.wait(...), Thread.join(...)
    Thread.sleep(100);
} catch (InterruptedException ie) {
    // re-interrupt the thread
    Thread.currentThread().interrupt();
    // deal with the interrupt by returning or something
    ...
}

请参阅:为什么在捕获任何 InterruptException 时调用 Thread.currentThread.interrupt()?

经常发生的情况是第 3 方代码由于代码错误而无法传播中断状态。那么你通常是 SOL,因为中断将被吞下并且take()方法不会抛出。

此外,重要的是要意识到Thread.interrupted() 清除中断标志。通常您要使用Thread.currentThread().isInterrupted()中断标志来测试状态。

是否有替代 BlockingQueue 实现解决了这个问题?

我不确定是否有问题。

于 2014-01-07T22:50:01.937 回答