【JUC并发编程】 终止模式之两阶段终止模式
1. 两阶段终止模式(Two Phase Termination)
想象一下,我们如何在线程t1中终止线程t2?我们马上就能想到使用线程对象的 stop() 方法。但是 stop() 会真正 杀死 线程,如果此线程锁住了某些共享资源,那么当杀死这个线程时,线程不会释放锁,其他线程无法获得锁,导致被锁住的共享资源就无法被别人使用了。
我们也许还会想到能不能使用 System.exit(int status) 呢?答案是不能!因为我们的目的只是停止程序中的某一个线程,而该方法会将程序中的所有线程都停止,从而退出程序。
以上提到的两种方法都无法解决我们遇到的问题,所以我们引入 两阶段终止模式 。
2. 案例
案例须知:
public void interrupt()实例方法,方法可以通知目标线程中断,并设置目标线程的中断标志位为true。public boolean isInterrupted()实例方法,方法可以判断线程是否被中断(通过检查中断标志位),并获取中断标志位,不会清除 打断标记 。public static boolean interrupted()Thread类的静态方法,返回当前线程的中断状态真实值(boolean类型)后会将当前线程的中断状态设为false,会清除 打断标记 。(返回当前值并清零置false)
给出以下案例,可以很好理解两阶段终止模式。
@Slf4j(topic = "c.Test13_")
public class Test13_ {
public static void main(String[] args) throws InterruptedException {
TwoPhaseTermination_ t = new TwoPhaseTermination_();
t.start();
Thread.sleep(3000);
t.stop();
}
}
@Slf4j(topic = "c.TwoPhaseTermination_")
class TwoPhaseTermination_ {
//监控线程
private Thread monitor;
//开启线程
public void start() {
monitor = new Thread(() -> {
while (true) {
Thread current = Thread.currentThread();
if(current.isInterrupted()){
log.debug("打断标记:{}",current.isInterrupted());
log.debug("料理后事");
break;
}
try {
Thread.sleep(1000);
log.debug("执行监控");
} catch (InterruptedException e) {
e.printStackTrace();
current.interrupt();
}
}
}, "monitor");
monitor.start();
}
//终结线程
public void stop(){
monitor.interrupt();
}
}
运行结果:

分析:
主线程创建一个监控线程 monitor 并让他运行,每隔1s monitor 线程打印一次“执行监控”。主线程方法3s后调用终结线程方法打断 monitor 线程。执行打断方法时 monitor 有两种状态。
- ①:在执行普通代码时被打断
- ②:在sleep时被打断
状态①时程序不会抛出异常,主程序直接将 monitor 线程打断,并“料理后事”。状态②时,monitor 线程会抛出一个 InterruptedException 异常并被自己捕获处理,在catch块中调用 interrupt() 方法,在自己的线程中将自己打断。
注:当线程处于被阻塞状态(sleep,wait,join等状态),在别的线程中调用当前线程对象的interrupt()方法,那么线程将立即退出被阻塞状态并抛出一个InterruptedException异常。

被折叠的 条评论
为什么被折叠?



