An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate. This is the usage emphasized in this lesson.
A thread sends an interrupt by invoking interrupt
on the Thread
object for the thread to be interrupted. For the interrupt mechanism to work correctly, the interrupted thread must support its own interruption.
How does a thread support its own interruption? This depends on what it's currently doing. If the thread is frequently invoking methods that throw InterruptedException
, it simply returns from the run
method after it catches that exception. For example, suppose the central message loop in the SleepMessages
example were in the run
method of a thread's Runnable
object. Then it might be modified as follows to support interrupts:
for (int i = 0; i < importantInfo.length; i++) { // Pause for 4 seconds try { Thread.sleep(4000); } catch (InterruptedException e) { // We've been interrupted: no more messages. return; } // Print a message System.out.println(importantInfo[i]); }
Many methods that throw InterruptedException
, such as sleep
, are designed to cancel their current operation and return immediately when an interrupt is received.
What if a thread goes a long time without invoking a method that throws InterruptedException
? Then it must periodically invoke Thread.interrupted
, which returns true
if an interrupt has been received. For example:
for (int i = 0; i < inputs.length; i++) { heavyCrunch(inputs[i]); if (Thread.interrupted()) { // We've been interrupted: no more crunching. return; } }
In this simple example, the code simply tests for the interrupt and exits the thread if one has been received. In more complex applications, it might make more sense to throw an InterruptedException
:
if (Thread.interrupted()) { throw new InterruptedException(); }
This allows interrupt handling code to be centralized in a catch
clause.
The interrupt mechanism is implemented using an internal flag known as the interrupt status. Invoking Thread.interrupt
sets this flag. When a thread checks for an interrupt by invoking the static method Thread.interrupted
, interrupt status is cleared. The non-static isInterrupted
method, which is used by one thread to query the interrupt status of another, does not change the interrupt status flag.
By convention, any method that exits by throwing an InterruptedException
clears interrupt status when it does so. However, it's always possible that interrupt status will immediately be set again, by another thread invoking interrupt
.
1 for (int i = 0; i < importantInfo.length; i++) { 2 // Pause for 4 seconds 3 try { 4 Thread.sleep(4000); 5 } catch (InterruptedException e) { 6 // We've been interrupted: no more messages. 7 return; 8 } 9 // Print a message 10 System.out.println(importantInfo[i]); 11 }
许多方法会抛出interruptException,例如sleep方法,这些方法如果接受到了中断请求就会立刻取消当前正在执行的操作。
如果一个线程运行了很长时间而没有执行抛出interruptedException的方法怎么办?那么它必须定时的执行thread.interrupted方法,当它接受到一个中断后它的返回值是true,例如:
1 for (int i = 0; i < inputs.length; i++) { 2 heavyCrunch(inputs[i]); 3 if (Thread.interrupted()) { 4 // We've been interrupted: no more crunching. 5 return; 6 } 7 }
在这个简单的实例中,这段代码只是简单的测试如果存在一个线程接受到了中断请求就会发生中断。在更复杂的应用中,它会抛出一个新的interruptException如下:
1 if (Thread.interrupted()) { 2 throw new InterruptedException(); 3 }
这使得一个catch块儿就能捕获到中断信息。
中断状态标志
中断机制是靠内部的中断状态来实现的。执行thread.interrupt方法时设置这个状态。当一个线程执行thread.interrupted静态方法的时候,中断状态就被清楚掉了。这个非静态的isInterrupted方法是让其他的线程查询这个线程的中断状态的方法,并不改变中断状态。
按照惯例,任何一个抛出interruptedException的方法,当抛出这个异常时都会清楚中断状态,但是,中断状态可能立即被其他的线程调用interrupt方法被重新设置。
养眼是必须滴