Java多线程设计模式(两阶段终止模式)
两阶段终止模式 (Two-Phase Termination Pattern)
两阶段终止模式 (Two-Phase Termination Pattern) 指的是当希望结束一个线程时,发出终止请求后线程不会立即停止,而是先完成当前的刷新或清理工作。线程进入“终止处理中”状态,在该状态下不再执行日常工作任务,而是专注于执行终止相关的操作。
设计考量
采用该模式主要基于以下三个关键因素:
- 安全结束线程
必须确保线程能够安全地结束。直接使用Thread.stop()方法存在风险,因为它会强制停止线程,无论线程执行到哪一行代码,都无法保证资源释放或数据一致性,可能导致对象处于不一致状态。 - 正常的终止处理
必须确保能够进行正常的收尾工作。在 Java 中,这一点通常可以使用finally代码块来实现,确保无论何种情况下退出循环,清理逻辑都能被执行。 - 高响应性的终止
收到终止请求后,如果线程正处于wait、sleep或join等阻塞状态,不应等到超时才终止,而应立即中断这些状态,进而执行终止操作。
工作流程
当一个线程正在执行周期性工作时,若在“作业阶段”收到了停止请求,该线程不应立即离开,而应先完成本次周期内部的工作,然后进入“善后阶段”完成清理工作。
所谓的两阶段终止,即中止“运作阶段”,并完成“善后阶段”,从而完整地结束线程的工作生命周期。
代码实现
两阶段终止线程的架构模式如下:
public class WorkerTerminalThread extends Thread {
// 已经送出终止请求为 true,初始化的时候为 false
// 由于该字段可能会被多个线程访问修改,为了保护就使用 volatile
private volatile boolean shutdownRequested = false;
// 终止请求
public void shutdownRequest() {
shutdownRequested = true;
interrupt();
}
public boolean isShutdownRequest() {
return shutdownRequested;
}
// 具体动作
public final void run() {
try {
while (!shutdownRequested) {
doWork();
}
} catch (InterruptedException e) {
// 捕获中断异常,配合标志位退出循环
} finally {
// 终止处理中的工作,不会进行平常操作,但是会进行终止处理
doShutdown();
}
}
// 具体工作操作
private void doWork() throws InterruptedException {
// 模拟周期性工作
}
// 终止后进行善后处理
private void doShutdown() {
// 清理资源
}
}原理解析
- Volatile 的作用
利用volatile修饰shutdownRequested字段,是因为该字段可能会被多个线程使用及修改。为了保证该字段的可见性,可以使用同步方法、同步代码块或volatile关键字。
使用volatile修饰的字段,强制该成员变量在每次被线程访问时,都从共享内存中重读该成员变量的值;而且当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。 标识位与中断状态的结合
这里运用了“标识位”和“中断状态”组合的方式来终止线程,之所以不单独使用其中一种,原因如下:- 仅利用标识位:无法使那些处于
wait、sleep或者join中的线程马上停止,响应性会很差。 - 仅利用中断 (interrupt):
interrupt仅仅对于wait、sleep或join处抛出异常。如果工作代码执行在catch里捕获了InterruptedException后未做处理,则此时中断标志可能被清除,导致中断不起作用。 - 组合使用:加入
interrupt后可以立刻使得处于阻塞状态的线程中断并抛出异常;配合shutdownRequested标识位,确保即使在异常被捕获的情况下,也能通过检查标志位正常退出循环。
- 仅利用标识位:无法使那些处于
说明:本文示例基于经典 Java 多线程模型编写。在现代 Java 并发编程中,更推荐使用ExecutorService配合Runnable或Callable任务,并通过shutdown()或Future.cancel()来管理线程生命周期,而非直接继承Thread类。但两阶段终止的核心思想(请求 + 清理)依然适用。
版权声明:本文为原创文章,版权归 戴老师的博客 所有,转载请联系博主获得授权。
本文地址:https://1diff.fun/archives/java-duo-xian-cheng-she-ji-mo-shi--liang-jie-duan-zhong-zhi-mo-shi.html
如果对本文有什么问题或疑问都可以在评论区留言,我看到后会尽量解答。