​ 如果我们想要在一个线程中优雅的终止另一个线程,可以使用interrupt方法实现,所谓优雅的终止指的是不是突然终止某个线程,而是告诉被终止的线程你即将被终止,让该线程可以在终止之前做一些工作

​ 假设我们需要实现一个监控类,这个类需要不断取获取系统当前的信息,并且系统可以决定终止该类的执行。

​ 我们的想法肯定是让一个线程不断的轮询,获取系统信息,那么如何终止该线程呢?如果直接调用stop方法,可能会造成死锁,因为有些资源会永远无法释放。

​ 正确的做法是,当想要终止另一个线程时,可以调用对应的线程的interrupt方法,该方法可以将线程的中断标识位置为true,接下来只需要通过isInterrupt来获取中断标识位(还有一个静态方法interruptted也能够获取中断标识位,与isInterrupt不同的是后者在返回标识位后会清除标识位,即如果标识位为true的话会置为false),如果为true直接跳出循环。需要注意的是如果当前需要中断的线程处于sleep、wait、join等状态时,调用它的interrupt会使该线程出现异常并清空中断标识位(置为false),因此我们需要再调用一次interrupt方法

​ 需要注意的是interrupt方法只会将线程的中断标识位置为true,并不会真的中断线程,具体的中断逻辑需要由程序员自己实现。

​ 总结

  • 1 中断标志位,默认false
  • 2 t2 —-> t1发出了中断协商,t2调用t1.interrupt(),中断标志位true
  • 3 中断标志位true,正常情况,程序停止,^_^
  • 4 中断标志位true,异常情况, 就是t1过程中调用了sleep 、join 、 wait 方法 会抛出一个 InterruptedException(中断异常),
  • 将会把中断状态将被清除,并且将收到InterruptedException 。中断标志位重新设置为false 导致无限循环
  • 5 所以如果要线程中调用sleep 、join 、 wait 方法 需要在catch块中,需要再次给中断标志位设置为true,2次调用停止程序才OK

原文链接:https://blog.csdn.net/m0_71149992/article/details/125504970

实现代码:

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
40
41
42
43
44
45
46
47
package com.deng;

public class InterruptTest {
private static Supervisor supervisor = new Supervisor();
public static void main(String args[]) throws InterruptedException {
supervisor.start();
Thread.sleep(3000);
supervisor.stop();
}
}

class Supervisor{
private Thread moniter;

/**
* 开始监控
*/
public void start(){
moniter = new Thread(() -> {
while(true){
boolean interrupted = Thread.currentThread().isInterrupted();
if(interrupted){
System.out.println("料理后事");
break;
}
try {
Thread.sleep(1000);
System.out.println("将监控信息保存至日志文件中");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}

}
},"moniter");

moniter.start();
}

/**
* 终止监控
*/
public void stop(){
moniter.interrupt();
}
}

image-20240310180339004