线程的interrupt
方法只是请求终止这个线程,而不是强制终止这个线程(总感觉这个方法名带有欺骗性,明明是中断的意思,却不中断线程,改成notifyInterrupt感觉更贴切些)。
public static void main(String[] args) throws InterruptedException {
Runnable r = () -> {
for (int i = 0; i < 2000; i++) {
System.out.println(i);
}
};
Thread t = new Thread(r);
t.start();
t.interrupt();
System.out.println("请求终止t线程");
}
我们看到尽管在程序一开始就向线程t发出了终止请求,但是线程t却依旧跑完了任务,并没有因为被调用interrupt而终止。
这时候你可能会有个疑问:既然interrupt
方法并不会中断线程,那这个方法有什么用呢?interrupt
方法会给线程设置上一个中断的标记,我们可以通过isInterrupted
方法来判断这个线程是否被请求中断,从而在任务中选择如何处理中断。
public static void main(String[] args) throws InterruptedException {
Runnable r = () -> {
for (int i = 0; i < 2000; i++) {
System.out.println(i);
boolean interrupted = Thread.currentThread().isInterrupted(); //默认情况下返回的是false,当线程被调用了interrupt方法后,会返回true
if (interrupted) {
System.out.println("收到线程终止请求,任务结束");
break;
}
}
};
Thread t = new Thread(r);
t.start();
t.interrupt();
System.out.println("请求终止t线程");
}
在上面代码中,我们通过Thread.currentThread
方法获取到线程,然后调用线程实例的isInterruptd
方法得到线程是否被请求终止。如果被请求终止,就结束这个for循环。
当一个线程是中断状态的时候,如果调用sleep或者wait,线程非但不会进入阻塞,而且还会抛出InterruptException
public static void main(String[] args) {
Runnable r = () -> {
Thread currentThread = Thread.currentThread();
System.out.println("中断状态" + currentThread.isInterrupted());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程苏醒了");
System.out.println("中断状态" + currentThread.isInterrupted());
};
Thread t = new Thread(r);
t.start();
t.interrupt();
}
我们可以看到,当我们对t线程调用了interrupt
之后,t线程的中断状态变成了true,接着让t线程sleep,线程不但没有休眠,而且直接就抛出异常了。同时我们还可以发现,在线程调用sleep之后,中断状态就被清除了。
以上代码我们证明了线程先进入中断状态,再被阻塞的时候,会抛出InterruptException
。那么当线程先进入阻塞(sleep或wait)的时候,再被调用interrupt
,又会如何呢?
下面我们用代码求证一下
public static void main(String[] args) throws InterruptedException {
Runnable r = () -> {
Thread currentThread = Thread.currentThread();
System.out.println("中断状态" + currentThread.isInterrupted());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程苏醒了");
System.out.println("中断状态" + currentThread.isInterrupted());
};
Thread t = new Thread(r);
t.start();
Thread.sleep(1000); //这里我们让main线程等待1秒再去执行t线程的interrupt。以确保t线程能够进入休眠
t.interrupt();
}
我们发现,对一个阻塞的线程调用interrupt
方法,线程也会抛出InterruptException
异常。
线程还有一个静态方法interrupted
,它和isInterrupted
一样都会检查当前线程是否被中断。但是不同之处在于interrupted
会清除当前线程的中断状态,而isInterrupted
不会。