今天同学给了我一道题目,发现自己对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
39
public class Thread2 {
public static void main(String[] args) throws InterruptedException {
final Thread sleepThread = new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};

Thread busyThread = new Thread() {
@Override
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
10
java.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()

中断调用该方法的线程。

其有两个作用:

  1. 将线程的中断状态设置为true(不论线程是处于运行的还是阻塞状态)
  2. 让被阻塞的线程抛出InterruptedException异常(同时中断状态为false)

这样,对于那些阻塞方法(比如 wait() 和 sleep())而言,当另一个线程调用interrupt()中断该线程时,该线程会从阻塞状态退出并且抛出中断异常。这样,我们就可以捕捉到中断异常,并根据实际情况对该线程从阻塞方法中异常退出而进行一些处理。

isInterrupted()

检测调用该方法的线程是否被中断,中断状态不会被清除

先看一下源码:

1
2
3
public boolean isInterrupted() {
return isInterrupted(false);
}

可以看到isInterrupted()和interrupted()一样调用了isInterrupted(),不过isInterrupted()参数ClearInterrupted为false,即不清除中断状态。

interrupted()

检测当前线程是否被中断,并且中断状态会被清除

同样先看下源码:

1
2
3
4
5
public 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()才将中断状态清除。