2011-10-13 115 views
3

我正在读取一些java线程中断,并且我不理解某些内容。希望有人会解释我。所以,它的完成下面的代码在退出之前恢复中断的不可撤销任务

public Integer getInteger(BlockingQueue<Integer> queue) { 
    boolean interrupted = false; 
    try { 
     while (true) { 
      try { 
       return queue.take(); 
      } catch (InterruptedException e) { 
       interrupted = true; 
       // fall through and retry 
      } 
     } 
    } finally { 
     if (interrupted) 
      Thread.currentThread().interrupt(); 
    } 
} 

的解释如下:不支持取消,但仍呼吁 中断阻塞方法将不得不叫他们在一个循环

活动, 检测到中断时重试。在这种情况下,他们应该在本地保存 中断状态,并在返回前将其恢复, 如清单所示。而不是立即捕获 InterruptedException。设置中断状态过早可能导致 无限循环,因为大多数可中断阻塞 方法检查入口处的中断状态,并且如果设置立即抛出 InterruptedException。 (可中断方法 通常阻止或做任何显著 工作之前轮询中断,以便作为响应中断,才可能进行。)

我不明白为什么我们要在本地保存中断状态。
我很乐意听到一些解释。

+0

嗯。有趣的... –

回答

2

通过设计该方法不能抛出InterruptedException。所以这意味着我们总是期望从队列中获得价值。但有人可能希望线程被中断,这就是为什么我们必须保存 - 在我们最终从队列中获取值之后恢复被中断的状态。

因此,线程只有在从队列中获取值后才能完成。

更新:查看take()方法的实现。它具有以下作为第一个发言:

public final void acquireInterruptibly(int arg) throws InterruptedException { 
    if (Thread.interrupted()) 
     throw new InterruptedException(); 
... 
} 
+0

好吧,我明白有人可以中断运行此方法的线程(和方法采取将thorw一个IE),但为什么不在catch块中调用“Thread.currentThread()。interrupt()”? – Bax

+0

“最可中断的阻塞方法检查入口处的中断状态并立即抛出InterruptedException,如果它被设置”。这意味着如果你将它设置在catch块中,它将在'take()'方法中再次循环,并且在做任何工作之前该方法可以立即退出(因为你已经设置了中断状态)。 – kan

+0

好的,理解的,谢谢,还有最后一个问题,finally块应该发生什么? – Bax

1

循环将结束,因为该语句

return queue.take(); 

这不是即使它看起来像一个紧密的循环。它只是阻塞一个元素,并在其可用时立即返回,并在发生中断时重试。

+0

只有当我们需要某种未被捕获的异常时,最后的阻塞怎么会达到? – Bax

+0

不,不管什么异常,finally块总是在try-block退出时执行。 – kan

+0

'finally'块总是*执行 - 不管是否抛出异常 - 所以在上面的代码中,如果元素可用,该方法将执行finally块并立即返回。它会阻止元素不可用。如果在阻塞时引发了InterruptedException,它只是为一个元素退役,但最终*,在所有情况下finally块将在方法返回之前执行。 – Bhaskar