多线程之两阶段终止模式
- IT业界
- 2025-09-01 19:27:02

两阶段终止模式
当某些线程正在运行时,如何去正确终止线程,如果直接强制终止线程(如调用 Thread.stop())会带来以下问题:
资源未释放:线程可能持有锁、打开文件或网络连接未关闭。数据不一致:线程可能正在修改共享数据,突然终止会导致数据损坏。不可控性:无法保证线程在安全点终止。两阶段终止模式(Two-Phase Termination Pattern)是一种多线程编程中安全终止线程的设计模式。它的核心思想是:在终止线程前,先发出终止请求(第一阶段),然后线程在完成必要清理工作后再真正终止(第二阶段)。这种模式避免了直接强制终止线程导致的资源泄露、数据不一致等问题
简单来说就是在一个线程T1中如何优雅的终止线程T2,给T2一个料理后事的机会
两阶段终止的实现步骤 第一阶段:发出终止请求 设置一个终止标志位,通知线程需要终止。如果线程处于阻塞状态(如 sleep()、wait()),需要通过**中断(Interrupt)**唤醒它。 第二阶段:线程响应终止请求 线程检测到终止标志位或中断信号后,停止接受新任务。执行清理工作(如释放锁、关闭文件)。安全终止线程。
如果你依然认为难以理解,可以用狼人杀的角度来解释一下:
使用Thread.stop()等强制终止线程,就是夜间被狼刀了,而两阶段终止模式是白天被票决,你还有发表遗言的机会
代码实现
这里启用了一个监控线程,在监控线程中用了一个死循环,并且用线程的中断状态作为标志位,如果线程在运行时被打断可直接进入第二阶段,若是线程在睡眠中被打断,在捕获InterruptedException后,重新设置中断状态,以便标志位终止线程
public class TwoPhase { /** * 两阶段终止模式: * 在一个线程T1中如何优雅的终止线程T2,给T2一个料理后事的机会 */ private Thread monitor; // 启动监控线程 public void start(){ monitor = new Thread(() -> { while (true){ Thread current = Thread.currentThread(); if (current.isInterrupted()){ // 判断线程中断状态 System.err.println("线程被打断,料理后事中............."); break; } try { Thread.sleep(2000); System.out.println("记录线程日志--------------------"); } catch (InterruptedException e) { e.printStackTrace(); System.err.println("------------->重置线程打断标识"); current.interrupt(); } } System.out.println("--------------线程已终止-----------------"); }); monitor.start(); } // 终止监控线程 public void stop(){ monitor.interrupt(); } }此时可以创建一个测试类,启动监控线程,等待几秒之后用stop终止该线程
public class TwoPhaseTest { public static void main(String[] args) throws InterruptedException { TwoPhase twoPhase = new TwoPhase(); twoPhase.start(); Thread.sleep(7000); twoPhase.stop(); } }控制台会依次输出信息:
记录线程日志-------------------- 记录线程日志-------------------- 记录线程日志-------------------- java.lang.InterruptedException: sleep interrupted at java.base/java.lang.Thread.sleep(Native Method) at juc2.TwoPhase.lambda$start$0(TwoPhase.java:20) at java.base/java.lang.Thread.run(Thread.java:834) ------------->重置线程打断标识 线程被打断,料理后事中............. --------------线程已终止-----------------大致流程图: #mermaid-svg-4tBCpnczjbevMleT {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-4tBCpnczjbevMleT .error-icon{fill:#552222;}#mermaid-svg-4tBCpnczjbevMleT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4tBCpnczjbevMleT .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-4tBCpnczjbevMleT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4tBCpnczjbevMleT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4tBCpnczjbevMleT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4tBCpnczjbevMleT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4tBCpnczjbevMleT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4tBCpnczjbevMleT .marker.cross{stroke:#333333;}#mermaid-svg-4tBCpnczjbevMleT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4tBCpnczjbevMleT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-4tBCpnczjbevMleT .cluster-label text{fill:#333;}#mermaid-svg-4tBCpnczjbevMleT .cluster-label span{color:#333;}#mermaid-svg-4tBCpnczjbevMleT .label text,#mermaid-svg-4tBCpnczjbevMleT span{fill:#333;color:#333;}#mermaid-svg-4tBCpnczjbevMleT .node rect,#mermaid-svg-4tBCpnczjbevMleT .node circle,#mermaid-svg-4tBCpnczjbevMleT .node ellipse,#mermaid-svg-4tBCpnczjbevMleT .node polygon,#mermaid-svg-4tBCpnczjbevMleT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4tBCpnczjbevMleT .node .label{text-align:center;}#mermaid-svg-4tBCpnczjbevMleT .node.clickable{cursor:pointer;}#mermaid-svg-4tBCpnczjbevMleT .arrowheadPath{fill:#333333;}#mermaid-svg-4tBCpnczjbevMleT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-4tBCpnczjbevMleT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-4tBCpnczjbevMleT .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-4tBCpnczjbevMleT .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-4tBCpnczjbevMleT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-4tBCpnczjbevMleT .cluster text{fill:#333;}#mermaid-svg-4tBCpnczjbevMleT .cluster span{color:#333;}#mermaid-svg-4tBCpnczjbevMleT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-4tBCpnczjbevMleT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-4tBCpnczjbevMleT .green>*{fill:#D5E8D4!important;stroke:#82B366!important;stroke-width:2px!important;color:#333!important;}#mermaid-svg-4tBCpnczjbevMleT .green span{fill:#D5E8D4!important;stroke:#82B366!important;stroke-width:2px!important;color:#333!important;}#mermaid-svg-4tBCpnczjbevMleT .orange>*{fill:#FFE6CC!important;stroke:#D79B00!important;stroke-width:2px!important;color:#333!important;}#mermaid-svg-4tBCpnczjbevMleT .orange span{fill:#FFE6CC!important;stroke:#D79B00!important;stroke-width:2px!important;color:#333!important;}#mermaid-svg-4tBCpnczjbevMleT .red>*{fill:#F8CECC!important;stroke:#B85450!important;stroke-width:2px!important;color:#333!important;}#mermaid-svg-4tBCpnczjbevMleT .red span{fill:#F8CECC!important;stroke:#B85450!important;stroke-width:2px!important;color:#333!important;}#mermaid-svg-4tBCpnczjbevMleT .diamond>*{stroke:#666!important;stroke-width:2px!important;shape:rhombus!important;}#mermaid-svg-4tBCpnczjbevMleT .diamond span{stroke:#666!important;stroke-width:2px!important;shape:rhombus!important;} ✅ 是 ❎ 否 🚫 无异常 ⚠️ 有异常 🔁 while true ❓ 是否被打断? 🛠️ 料理后事 ⏹️ 结束循环 💤 sleep(2000) 📝 执行监控记录 ⚡ 设置打断标记
多线程之两阶段终止模式由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“多线程之两阶段终止模式”
上一篇
地表放置机场和飞机(十)
下一篇
嵌入式八股文(四)计算机网络篇