Java 为什么将Thread.currentThread().isInterrupted()与try/catch一起使用

Java 为什么将Thread.currentThread().isInterrupted()与try/catch一起使用,java,multithreading,Java,Multithreading,我发现这种结构在java思考的多线程章节中很流行: 然而,我现在认为,当且仅当阻塞的wait()、sleep()或I/O抛出InterruptedExeption时,while循环才会退出,为什么不改为使用while(true)?或者仅仅因为Thread.currentThread().isInterrupted()是规范的?您也可以从外部使用Thread.interrupt()中断线程。所以说它基本上是一个内置布尔标志 在这种情况下,你是对的。您可以使用while(true),因为当发生中断异

我发现这种结构在java思考的多线程章节中很流行:


然而,我现在认为,当且仅当阻塞的
wait()
sleep()
I/O
抛出
InterruptedExeption
时,while循环才会退出,为什么不改为使用
while(true)
?或者仅仅因为
Thread.currentThread().isInterrupted()
是规范的?

您也可以从外部使用
Thread.interrupt()
中断线程。所以说它基本上是一个内置布尔标志


在这种情况下,你是对的。您可以使用
while(true)
,因为当发生
中断异常时,它将中断循环。作者可能想用一种连贯的方式来解释它。可能有一章是关于如何停止一条无止境的线。

这是一个人为的、相当糟糕的例子。你说得对,while(true)
是一个完美的替代品

sleep
wait
已检查此标志。他们使用它来知道是否抛出异常

因此,本守则:

public void run(){
    try{
        while(!Thread.currentThread().isInterrupted()){
            Thread.sleep(100);
        }
    }catch(InterruptedExeption e){

    }
}
基本上表示这种逻辑(伪代码):

这显然有点复杂,毫无意义


更重要的是,
Thread.sleep
实际上调用了
interrupted
,而不是
isInterrupted
,这是一个微妙的不同,因为它实际上重置了标志,因此线程看起来是不间断的。

显然是根据:

如果此线程在调用对象类的wait()、wait(long)或wait(long,int)方法时被阻塞,或者在调用此类的join()、join(long)、join(long,int)、sleep(long)或sleep(long,int)方法时被阻塞,则其中断状态将被清除,并将接收到InterruptedException


因此,
isInterrupted()
的返回值和
InterruptedException
的含义不一定相同。请参阅API文档以了解更多其他条件。

由于所有可运行操作都是睡眠,因此不需要对中断进行检查。但正如你从评论中可以看出的,这是一个更大的例程的模型。虽然sleep和wait抛出InterruptedException,但阻塞I/O调用(列在注释中)不会,不等待或睡眠的CPU密集型代码也不会


Bruce E在这里所做的是为您提供一个模板,用于处理抛出InterruptedException的情况(他使用它退出循环),以及处理不涉及睡眠或等待且不抛出InterruptedException的情况。它让读者知道他们有一个显式检查标志的选项,并演示了正确的方法(而不是使用中断方法来清除标志)

因此,事实上,如果线程正在调用
wait
sleep
,那么这些方法无论如何都会重置该标志,使得在循环时从外部检查它几乎毫无意义。@Michael我同意。事实上,我不记得在我的代码中调用过
isInterrupted()
。我的回答只是试图为书中的示例代码找到一些基本原理。如果您感兴趣,这里会涉及到这一点。是的,但是这个“模板”只对重复循环相当快的操作的runnable有用。在循环体中输入的任何慢代码都需要一段时间才能终止(在这种情况下,如果可能的话,可能代码应该定期检查标志)。任何不循环的内容都不能使用此模板。作为一个模板,它实际上是一个令人难以置信的利基。@michael:这只是一个起点。让人们知道isInterrupted方法存在是件好事,但这不是一个好的起点。仅仅因为它在一本书中并不意味着它是好的。还有更好的。
public void run(){
    try{
        while(!Thread.currentThread().isInterrupted()){
            Thread.sleep(100);
        }
    }catch(InterruptedExeption e){

    }
}
try {
    while(!Thread.currentThread().isInterrupted())
    {
        /* Thread.sleep */
        boolean keepSleeping = true;
        while(keepSleeping)
        {
            if (Thread.currentThread().isInterrupted())
            {
                throw new InterruptedExeption();
            }
            actualSleep(/*a very small amount of time*/);
            if (/* we've slept long enough*/)
            {
                keepSleeping = false;
            }
        }
        /* End Thread.sleep */
    }
}catch(InterruptedExeption e){

}