如果你有一个消费者线程的句柄,你可以中断它。随着您提供的代码,这将杀死消费者。我不会期望生产者有这个;它可能不得不以程序控制器的方式回调,让它知道它已经完成。然后控制器将中断消费者线程。
在遵循中断之前,您可以随时完成工作。例如:
class QueueConsumer implements Runnable {
@Override
public void run() {
while(!(Thread.currentThread().isInterrupted())) {
try {
final ComplexObject complexObject = myBlockingQueue.take();
this.process(complexObject);
} catch (InterruptedException e) {
// Set interrupted flag.
Thread.currentThread().interrupt();
}
}
// Thread is getting ready to die, but first,
// drain remaining elements on the queue and process them.
final LinkedList remainingObjects;
myBlockingQueue.drainTo(remainingObjects);
for(ComplexObject complexObject : remainingObjects) {
this.process(complexObject);
}
}
private void process(final ComplexObject complexObject) {
// Do something with the complex object.
}
}
我实际上更喜欢以某种方式中毒排队。如果你想杀死线程,请求线程自己杀死。
(很高兴看到有人正确处理InterruptedException。)
现在,有一个理解,没有人实际上读过,这是交易。如果线程当前在中断时阻塞,线程将只会收到InterruptedException。在这种情况下,Thread.interrupted()将返回false。如果没有阻塞,它将不会收到此异常,而是Thread.interrupted()将返回true。因此,你的循环保护应该是绝对的,不管怎么样,检查Thread.interrupted(),否则有可能丢失线程中断。
所以,既然你正在检查Thread.interrupted(),无论什么,你被迫捕获InterruptedException(并且应该处理它,即使你没有被迫),你现在有两个代码区域处理相同的事件,线程中断。处理这种情况的一种方法是将它们归一化为一个条件,这意味着布尔状态检查可以抛出异常,或异常可以设置布尔状态。我选择了以后。
编辑:请注意,静态Thread#interrupt方法会清除当前线程的中断状态。