场景:我们如何在t1 线程中终止t2 线程呢?
错误思路❌
- stop():调用Thred的静态方法直接杀死线程
- System.exit(int):除了直接杀死线程,还会直接停止掉运行线程的应用程序
为什么说这是错误的思路呢?比如t1 调用了 t2线程,此时需要终止掉t2线程,但是在t2 线程体中还有被锁住的共享资源,此时还未释放锁,如果直接调用stop()方法去终止线程,那么t1就无法得到共享资源,显然这两种方法存在一定的弊端!!
两阶段终结模式
引入两阶段终结模式,也就是为了解决上述存在的弊端。简单理解为两步:
<mark>第一阶段</mark>:打断线程运行状态
<mark>第二阶段</mark>:处理和释放其它共享资源
此终结模式并不是真正意义上面的终止,也就是不能通过调用线程的stop()方法或者System.exit(0)方法进行杀死线程。
看一个例子:
场景:我们需要在main线程中终止t1(监控)线程的运行
@Slf4j(topic = "c.Test7")
public class Test7 {
//定义监控线程
private Thread thread;
public static void main(String[] args) throws InterruptedException {
Test7 test7 = new Test7();
//启动线程
test7.start();
Thread.sleep(1000);
//终止线程
test7.stop();
}
//启动监控线程
public void start(){
thread = new Thread("t1"){
@Override
public void run() {
//执行监控
while (true){
boolean interrupted = currentThread().isInterrupted();
//是否被打断
if (interrupted){
log.debug("监控系统被打断");
//处理阶段2的业务代码...
break;
}
try {
Thread.sleep(10000);
log.debug("执行监控记录");
} catch (InterruptedException e) {
e.printStackTrace();
thread.interrupt(); //重新将打断标志置为true
}
}
}
};
thread.start();
}
//停止监控线程
public void stop(){
thread.interrupt();
}
}
分析:
我们知道当没有遇到堵塞状态的异常抛出时,线程被打断,打断标志会被置为true,此时正常终止,当遇到堵塞状态的异常抛出,此时打断标志会被置为false,会被异常InterruptedException 抓住来处理,要注意的是要把打断标志置为true,进入if后我们应该做的是<mark>阶段2</mark>的事情,才能正常退出线程!