我发现这个结构在 Thinking in java 的多线程章节中很流行:
public void run(){
try{
while(!Thread.currentThread().isInterrupted()){
// do something blocked like wait(), sleep() or I/O
}
}catch(InterruptedExeption e){
}
}
但是我认为,当且仅当被阻止的wait()
,sleep()
或I/O
抛出InterruptedExeption
时,while循环才会退出,为什么不使用{{1}而不是?或者仅仅因为while(true)
只是规范?
答案 0 :(得分:3)
由于所有Runnable都是睡眠状态,因此检查中断是不必要的。但正如你从评论中可以看出的那样,这是一个更大的惯例的模型。当sleep和wait抛出InterruptedException时,阻塞I / O调用(在注释中列出)不会,并且不等待或休眠的CPU密集型代码也不会。
Bruce E在这里做的是为你提供一个模板,它可以处理抛出InterruptedException的情况(他用它来退出循环),还可以处理没有睡眠或等待的情况。没有抛出InterruptedException。它让读者知道他们可以选择明确检查标志,并演示正确的方法(与使用中断方法清除标志相反)。
答案 1 :(得分:0)
您也可以从外部用Thread.interrupt()
中断线程。所以说它基本上是一个内置的布尔标志。
在这种情况下,你是对的。您可以使用while(true)
,因为它会在发生InterruptedException
时突破循环。作者可能想在一个有凝聚力的问题上解释它。关于如何阻止无尽的线程,可能会有一章。
答案 2 :(得分:0)
这是一个人为的,相当糟糕的例子。你是对的,while (true)
是一个非常好的替代品。
sleep
和wait
已经检查此标记。他们使用它来知道是否抛出异常。
因此这段代码:
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){
}
这显然有点复杂和毫无意义。
更重要的是,Thread.sleep
实际上调用了interrupted
而不是isInterrupted
,因为实际上重置了标志,所以这是微妙的不同所以线程不会中断。
答案 3 :(得分:0)
显然是根据API Doc:
如果在调用Object类的wait(),wait(long)或wait(long,int)方法,或者join(),join(long),join(long)时阻塞了这个线程,int),sleep(long)或sleep(long,int),此类的方法,然后其中断状态将清除,它将收到InterruptedException 。
因此isInterrupted()
和InterruptedException
的返回值并不一定意味着同样的事情。有关更多其他条件,请参阅API文档。