Java 这个示例代码是简单易懂的,还是有理由使用interrupt()呢
我正在阅读以下示例代码:Java 这个示例代码是简单易懂的,还是有理由使用interrupt()呢,java,multithreading,concurrency,interrupted-exception,interruption,Java,Multithreading,Concurrency,Interrupted Exception,Interruption,我正在阅读以下示例代码: public final class Indexer implements Runnable { private final BlockingQueue<File> queue; public Indexer(BlockingQueue<File> queue) { this.queue = queue; } @Override public void run() {
public final class Indexer implements Runnable {
private final BlockingQueue<File> queue;
public Indexer(BlockingQueue<File> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
while (true) {
queue.take();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public final类索引器实现可运行{
私有最终阻塞队列;
公共索引器(阻止队列){
this.queue=队列;
}
@凌驾
公开募捐{
试一试{
while(true){
queue.take();
}
}捕捉(中断异常e){
Thread.currentThread().interrupt();
}
}
}
随附说明:
恢复中断。有时候你不能扔
InterruptedException,例如,当您的代码是
可运行的。在这些情况下,您必须捕获InterruptedException
并通过调用当前设备上的中断来恢复中断状态
线程,以便调用堆栈中较高的代码可以看到
发出了中断,如清单5.10所示
在示例代码中,“调用堆栈上方的代码”如果执行此代码,将永远不会看到中断,或者我是否做出了错误的推断?这里的线程在调用interrupt()
后就死了,对吗
所以这个interrupt()
唯一有用的方法就是如果它在一个循环中,对吗
这里的线程在调用interrupt()后就死了,对吗
执行线程在中断后不会完成,您认为thread\stop
。即使在runnable完成后,线程也可以继续运行。Runnable只是线程运行的任务
在该任务完成后,线程是否需要知道发生了中断?如果线程需要响应其他取消请求,而这是由另一个线程完成的,该怎么办
因为你只是一个可运行的任务,你没有这些答案,因此你应该让线程知道中断发生了,这样线程就可以按照它想要的方式处理它。指定Thread.interrupt()的效果
如果该线程在调用对象类的wait()、wait(long)或wait(long,int)方法时被阻塞,或者在调用该类的join()、join(long)、join(long,int)、sleep(long)或sleep(long,int)方法时被阻塞,那么它的中断状态将被清除,并接收到InterruptedException
如果在中断通道上的I/O操作中阻塞了此线程,则通道将关闭,线程的中断状态将被设置,线程将收到ClosedByInterruptException
如果该线程在选择器中被阻塞,那么该线程的中断状态将被设置,并且它将立即从选择操作返回,可能带有非零值,就像调用了选择器的唤醒方法一样
如果前面的条件都不成立,那么将设置该线程的中断状态
注意最后一段;本质上,除非线程当前正在执行上述等待类型的操作之一,否则中断线程只会设置一个标志,但不会影响控制流。无论调用来自不同的线程还是受害者线程本身,这都是正确的
换言之:
try {
while (true) {
queue.take();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// When an interrupt is received, the thread resumes
// execution here. It will notice the effect of the
// Thread.currentThread().interrupt() only, if it tries
// to perform any of the mentioned special wait operations
// here.
synchronized (someLockObject) {
while (!someCondition) {
// Will immediately terminate with an `InterruptedException`,
// since we properly restored the interrupt status
// above.
someLockObject.wait();
}
}
该方法实现了当前调用堆栈中的所有代码都有机会识别中断,并执行必要的清理和“有序”关闭。如果您不恢复中断状态,那么遵循try
/catch
的代码可能会错误地认为一切正常,应该恢复正常执行。在Java中,您需要处理线程中断。为此,必须轮询Thread.isInterrupted()
。当您的代码是可运行的
的一部分时,您需要在发生中断异常时设置线程的中断标志
,以便此线程运行的后续任务(调用堆栈中较高的代码)可以轮询线程。isInterrupted()
并适当处理中断。这也给了线程一个干净退出的机会,而不是立即杀死它。这就是Thread.stop()
所做的
Object.wait
和Thread.sleep
是两个示例,它们首先检查标志并抛出InterruptedException
,如果设置了它。在编写玩具示例时,我对此感到矛盾,我不喜欢在示例中插入类似Thread.currentThread().interrupt()
的东西,因为在示例中它什么都不做,但我也希望我的示例演示良好的实践,这意味着设置中断标志
如果您将Runnable传递到一个线程中,那么显然没有任何东西会读取作为Runnable所做的最后一件事恢复的中断。当线程终止时,中断标志值不再可用
如果Runnable被传递给执行器,那么执行器负责在其线程上设置中断标志。此外,执行者还应该知道,不要依赖任务来恢复中断标志。因此,如果执行者任务不恢复中断状态,这通常不重要
但也可能有边缘案例;Runnable可能需要由当前线程运行,而不是交给另一个线程。例如,如果您将任务提交给具有拒绝策略的执行器,该策略使任务在调用线程中运行,那么如果调用线程正在运行从执行器拒绝的任务,并且该执行器没有恢复中断标志,则调用线程的中断可能会丢失
最好能够更改executor的配置,而不必担心该配置中的任务是否表现良好。任务是有漏洞的抽象,这在一般情况下是不可能的,但对于这个特定的问题,它是:让您的任务在所有情况下都恢复中断标志,以防万一