2013-01-03 116 views
0

我正想通过Oracle的Java教程的主题,我看到这个例子java的混乱

源:http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

如果一个线程进入一个很长一段时间,而不必调用一个方法抛出InterruptedException?然后它必须定期调用Thread.interrupted,如果接收到中断,则返回true。例如:

for (int i = 0; i < inputs.length; i++) { 
     heavyCrunch(inputs[i]); 
     if (Thread.interrupted()) { 
      // We've been interrupted: no more crunching. 
     return; 
} 

教程添加: 中断机构被使用被称为中断状态的内部标志实现。调用Thread.interrupt设置此标志。当一个线程通过调用静态方法Thread.interrupted来检查中断时,中断状态被清除。一个线程用于查询另一个线程的中断状态的非静态isInterrupted方法不会更改中断状态标志。

按照惯例,任何通过抛出InterruptedException退出的方法都会清除中断状态。但是,通过另一个线程调用中断,可能会立即再次设置中断状态。

现在我很困惑。它何时发生?如果有中断,不应该线程收到InterruptedException?

当有人可能使用这些方法检查他们的代码? Thread.interrupt(该标志)是静态的,所以通过上面的检查,我们实际上检查是否有任何踏板已经中断?即使是这样,根据教程,当一个线程通过调用静态方法Thread.interrupted检查中断时,中断状态被清除。任何通过抛出InterruptedException而退出的方法在清除中断状态时会清除中断状态

因此,我是否错过了某些东西?或者这只是有用的,如果某个线程收到中断,但不检查它,或不扔它?

+0

问题的症结在于你要么手动检查你的线程的中断状态,要么你会处理一个'InterruptedException'。 – Perception

回答

2

并非所有的方法,在Thread,抛出InterrupedException s。这在睡眠和等待中,或者任何耗时的方法中最常见。这是Java实现它的方式。 (sleep(...)native代码,所以我不能告诉你的来源。)

例如:

try { 
    Thread.sleep(1000); // one sec 
} catch(InterruptedException e){ 
} 

但你不能强迫包括一个简单的for循环,在try..catch条款。

如果你的子类Thread,你应该遵循约定,张贴。


关于第二个问题,关于static方法,这里的内部代码:

public static boolean interrupted() { 
    return currentThread().isInterrupted(true); 
} 

所以你可以看到,它只是设置,在当前线程的实例

+0

感谢MouseEvent,但从我的理解,如果有睡眠或等待,并且我们做t.interrupt,它会抛出InterruptedException。你可以给我一个例子吗。 – Athena

1

很多次一个线程正在做很多等待或阻止。在几乎所有这些情况下,执行阻塞的方法都支持InterruptedException。一些示例:

  1. Thread.sleep(millis);
  2. obj = arrayBlockingQueue.take();
  3. obj.wait();

引用的文章指出的是,如果你的线程没有被阻塞,意味着没有支持InterruptedException的方法,那么你有责任检查你的线程是否被中断。这通过测试Thread.interrupted()来完成。

方法Thread.interrupt()其实不是静态的,而是从另一个线程调用来中断该线程。请参阅以下内容:

Thread.interrupt()

这是否有意义?

5

这Thread.interrupted实现

public static boolean interrupted() { 
    return currentThread().isInterrupted(true); 
} 

private native boolean isInterrupted(boolean ClearInterrupted); 

,你可以看到它可以检查/复位只有当前线程的中断状态。如果它不是静态的,你可以在其他线程上调用它,并重置API不允许的状态。