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的配置,而不必担心该配置中的任务是否表现良好。任务是有漏洞的抽象,这在一般情况下是不可能的,但对于这个特定的问题,它是:让您的任务在所有情况下都恢复中断标志,以防万一