中断可以理解为线程的一个标识位属性,它表示一个运行中的线程是否被其他线程进行了中断操作。中断好比其他线程对该线程打了个招呼,其他线程通过调用该线程的interrupt()
方法对其进行中断操作。
1 | public static void main(String[] args) { |
输出1
2
3
4
5
6
7
8
9
10
11false-1
false-2
false-3
false-4
false-5
true-6
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at ThreadInterrupt.lambda$main$0(ThreadInterrupt.java:19)
at java.lang.Thread.run(Thread.java:748)
false-7
线程通过检查自身是否被中断来进行响应,线程通过方法isInterrupted()来进行判断是否被中断,也可以调用静态方法Thread.interrupted()对当前线程的中断标识位进行复位true-6
。如果该线程已经处于终结状态,即使该线程被中断过,在调用该线程对象的isInterrupted()时依旧会返回false。
从上面false-7
可以看到,抛出InterruptedException的方法,Java虚拟机会先将该线程的中断标识位清除,然后抛出InterruptedException,此时调用isInterrupted()方法将会返回false。
interrupt有两个非常类似的方法,interrupted 和 islnterrupted。Interrupted 方法是一个静态方法, 它检测当前的线程是否被中断。 而且, 调用 interrupted 方法会清除该线程的中断状态。另一方面,islnterrupted 方法是一个实例方法,可用来检验是否有线程被中断。调用这个方法不会改变中断状态。1
2
3
4
5
6
7
8
9void interrupt()
实例方法,针对线程对象。向线程发送中断请求。线程的中断状态将被设置为 true。如果目前该线程被一个sleep调用阻塞,那么,InterruptedException 异常被抛出。
•static boolean interrupted()
静态方法,针对当前线程。测试当前线程(即正在执行这一命令的线程)是否被中断。注意,这是一个静态方法。
这一调用会产生副作用—它将当前线程的中断状态重置为 false。
• boolean islnterrupted()
实例方法,针对线程对象。测试线程是否被终止。不像静态的中断方法,这一调用不改变线程的中断状态。
•static Thread currentThread()
返回代表当前执行线程的 Thread 对象。
扩展
当对一个线程调用interrupt方法时,线程的中断状态将被置位。这是每一个线程都具有的 boolean标志。每个线程都应该不时地检査这个标志,以判断线程是否被中断。
要想弄清中断状态是否被置位,首先调用静态的 Thread.currentThread 方法获得当前线
程,然后调用 islnterrupted 方法:1
2
3
4while (!Thread.currentThread().islnterrupted() && more work to do)
{
do more work
}
但是,如果线程被阻塞,就无法检测中断状态。这是产生 InterruptedExceptioii 异常的地方。当在一个被阻塞的线程(调用 sleep 或 wait) 上调用 interrupt 方法时,阻塞调用将会被Interrupted Exception 异常中断
。
中断一个线程不过是引起它的注意。被中断的线程可以决定如何响应中断。某些线程是如此重要以至于应该处理完异常后, 继续执行,而不理会中断。这种线程的 run 方法具有如下形式:1
2
3
4
5
6
7
8
9
10
11
12
13Runnable r = () -> {
try{
while (!Thread.currentThread().islnterrupted0 && more work to do){
do more work
Thread,sleep(delay);
}
}catch(InterruptedException e){
// thread was interr叩ted during sleep or wait
}finally{
cleanup, ifrequired
}
// exiting the run method terminates the thread
};
如果在每次工作迭代之后都调用 sleep 方法(或者其他的可中断方法)islnterrupted 检测既没有必要也没有用处。如果在中断状态被置位时调用 sleep 方法,它不会休眠。相反,它将清除这一状态并拋出 IntemiptedException。因此,如果你的循环调用 sleep,不会检测中断状态。