Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么在阻塞调用之前过早设置中断状态会导致无限循环?_Java_Multithreading - Fatal编程技术网

Java 为什么在阻塞调用之前过早设置中断状态会导致无限循环?

Java 为什么在阻塞调用之前过早设置中断状态会导致无限循环?,java,multithreading,Java,Multithreading,我正在读“实践中的并发”,在第6章“对中断的响应”中,它说 过早设置中断状态可能会导致无限循环,因为大多数可中断的阻塞方法会在进入时检查中断状态,如果设置了中断,则会立即抛出InterruptedException。(可中断方法通常在阻塞或执行任何重要工作之前对中断进行轮询,以便在阻塞或执行任何重要工作之前对中断作出响应,以便尽可能对中断作出响应) 公共任务getNextTask(阻塞队列){ 布尔值=假; 试一试{ while(true){ 试一试{ 返回队列。take(); }捕捉(中断异常

我正在读“实践中的并发”,在第6章“对中断的响应”中,它说

过早设置中断状态可能会导致无限循环,因为大多数可中断的阻塞方法会在进入时检查中断状态,如果设置了中断,则会立即抛出InterruptedException。(可中断方法通常在阻塞或执行任何重要工作之前对中断进行轮询,以便在阻塞或执行任何重要工作之前对中断作出响应,以便尽可能对中断作出响应)

公共任务getNextTask(阻塞队列){
布尔值=假;
试一试{
while(true){
试一试{
返回队列。take();
}捕捉(中断异常e){
中断=真;
//失败并重试
}
}
}最后{
如果(中断)
Thread.currentThread().interrupt();
}
}
假设代码是

public Task getNextTask(BlockingQueue<task> queue){
boolean interrupted=false;
        while(true){
        /*i get this part that before the take() function threads     interrupted status is checked*/
            return queue.take();
        }catch(InterruptedException e){
                interrupted=true;
                Thread.currentThread().interrupt();
            }
    }//end of while
}
公共任务getNextTask(阻塞队列){
布尔值=假;
while(true){
/*在检查take()函数线程的中断状态之前,我得到了这一部分*/
返回队列。take();
}捕捉(中断异常e){
中断=真;
Thread.currentThread().interrupt();
}
}//结束
}

现在,为什么最后一个函数会导致无限循环,因为我已经将threrad的中断状态设置回false,根据我的理解,在阻塞调用轮询线程的中断状态期间,它将检查它是否被设置,它将发现它为false,然后继续调用。那么无限循环在哪里呢op进入画面?

将抛出一个
中断异常
,因为
take()
方法检查中断。此检查/抛出通常采用以下形式:

if (Thread.currentThread.interrupted()) {  // Checks and clears the interrupted flag.
  throw new InterruptedException();
}
然后捕获
InterruptedException
,恢复中断标志,并再次调用
take()
。这将检查中断,发现线程已中断,然后抛出
InterruptedException

然后捕获
InterruptedException
,恢复中断标志,并再次调用
take()
。这将检查中断,发现线程已中断,然后抛出
InterruptedException

然后捕获
InterruptedException
,恢复中断标志,并再次调用
take()
。这将检查中断,发现线程已中断,然后抛出
InterruptedException


等等。

第二个代码甚至不会编译。如果
队列中出现
队列,那么第一个代码段将落入无限循环。take
总是被中断,并且永远不会返回任何内容。@michalk你能提供一个更清楚的例子来解释为什么吗?如果调用了重置,那么检查中断的代码为什么会抛出InterruptedException beca现在使用它的中断状态已被清除?我已将“重置”改写为“还原”。因此,一旦线程被中断并抛出InterruptedException,它的中断标志将被清除?因此,在上面编写的代码中,如果我将“if(Thread.currentThread.interrupted()”,则在catch块中,它将变成false?@GaganSingh不一定。interrupted标志和interrupted exception是表示中断的正交机制。
Thread.interrupted()
清除中断标志,
Thread.isInterrupted()
不。但是
interrupted()
倾向于在抛出异常之前立即使用,以便清除标志,使其看起来不会“双重中断”(这不是一件事;对于处理异常的人来说,这只是一种令人困惑的状态)。
if (Thread.currentThread.interrupted()) {  // Checks and clears the interrupted flag.
  throw new InterruptedException();
}