今天同学给了我一道题目,发现自己对interrupt()、isInterrupted()、interrupted()理解的不好。
interrupt()、isInterrupted()、interrupted()
我们先看一下例子。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39public class Thread2 {
public static void main(String[] args) throws InterruptedException {
final Thread sleepThread = new Thread() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread busyThread = new Thread() {
public void run() {
while (true) {
}
}
};
sleepThread.start();
busyThread.start();
sleepThread.interrupt();
busyThread.interrupt();
Thread.sleep(2000);
System.out.println("sleepThread 0: " + sleepThread.isInterrupted());
while (sleepThread.isInterrupted()) ;
System.out.println("sleepThread 1: " + sleepThread.isInterrupted());
System.out.println("busyThread 1: " + busyThread.isInterrupted());
System.out.println("sleepThread 2: " + sleepThread.interrupted());
System.out.println("busyThread 2: " + busyThread.interrupted());
System.out.println("sleepThread 3: " + sleepThread.isInterrupted());
System.out.println("busyThread 3: " + busyThread.isInterrupted());
}
}
运行结果:1
2
3
4
5
6
7
8
9
10java.lang.InterruptedException: sleep interrupted
at java.base/java.lang.Thread.sleep(Native Method)
at test.Thread2$1.run(Thread2.java:9)
sleepThread 0: false
sleepThread 1: false
busyThread 1: true
sleepThread 2: false
busyThread 2: false
sleepThread 3: false
busyThread 3: true
很奇怪,为什么busyThread 2变成了false,接着busyThread 3又是true了呢?
认识interrupt()、isInterrupted()、interrupted()
interrupt()
中断调用该方法的线程。
其有两个作用:
- 将线程的中断状态设置为true(不论线程是处于运行的还是阻塞状态)
- 让被阻塞的线程抛出InterruptedException异常(同时中断状态为false)
这样,对于那些阻塞方法(比如 wait() 和 sleep())而言,当另一个线程调用interrupt()中断该线程时,该线程会从阻塞状态退出并且抛出中断异常。这样,我们就可以捕捉到中断异常,并根据实际情况对该线程从阻塞方法中异常退出而进行一些处理。
isInterrupted()
检测调用该方法的线程是否被中断,中断状态不会被清除。
先看一下源码:1
2
3public boolean isInterrupted() {
return isInterrupted(false);
}
可以看到isInterrupted()和interrupted()一样调用了isInterrupted(),不过isInterrupted()参数ClearInterrupted为false,即不清除中断状态。
interrupted()
检测当前线程是否被中断,并且中断状态会被清除。
同样先看下源码:1
2
3
4
5public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
private native boolean isInterrupted(boolean ClearInterrupted);
如果一个线程已经被终止了,中断状态是否被重置取决于ClearInterrupted的值,即ClearInterrupted为true时,中断状态会被重置,为false则不会被重置。
需要强调的是:interrupted()是static方法,调用的时候是Thread.interrupted(),而isInterrupted()是实例方法,调用时是用线程的实例调用。
因此,我们可以很容易知道上述例子中busyThread.isInterrupted()还是通过当前线程调用的,而当前线程为main,自然结果为false。
另一个问题
为什么sleepThread 0 isInterrupted()的返回结果是false,同时如果将其上一行代码Thread.sleep(2000);
删掉,其返回结果却是true。
我们是上面说过线程一旦被中断,isInterrupted()返回true,而一旦sleep等方法抛出异常,它将清除中断状态,此时方法将返回false。
再来,去掉Thread.sleep(2000);
为什么返回结果是true呢,很简单呀这是两个线程,main线程需要等一等sleepThread这个线程抛出异常后,isInterrupted()才将中断状态清除。