Java并发 | 13.[设计模式] 两阶段终止线程
文章目录
- 1. 错误的终止线程方式
- 错误①:直接用 t1.stop( ) 停止线程
- 错误②:使用 System.exit( int ) 停止进程
- 2. 更优雅的终止方式——两阶段终止模式
- 2.1. 核心思想
- 2.2. 如何实现?
- 3. 代码示例
- 参考资料
1. 错误的终止线程方式
错误①:直接用 t1.stop( ) 停止线程
该方法会直接杀死线程。
若在此之前线程锁住了共享资源,在它被杀死后就 再也没有机会将锁释放,其他线程将永远无法获取锁。
错误②:使用 System.exit( int ) 停止进程
该方法会直接 停止整个进程 …多少是有些滥杀无辜了。
2. 更优雅的终止方式——两阶段终止模式
2.1. 核心思想
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-49R8yGIR-1661879275561)(http://xyx-eshang.oss-cn-heyuan.aliyuncs.com/img/2022/08/30/2022:08:30-17:08:47:794)]
将终止线程拆分成两个阶段,给需要终止的线程一个 “料理后事” 的机会:
第一个阶段只是发出指令,第二个阶段则是目标线程针对发出的指令,先「料理完后事」,再自主停止线程。
2.2. 如何实现?
在真正执行操作之前,先判断该线程是否曾被打断(curThread.isInterrupted( )),一旦检测到被打断,则将当前锁住的所有资源释放,料理完所有后事后,自主停止线程。
需要注意,如果线程在休眠状态被打断,通常需要在 catch 代码块中将打断标记重新设为true,以确保下次能进入if代码块。
private static void test(){
Thread t1 = new Thread(() -> {
Thread curThread = Thread.currentThread();
while (true){
if (curThread.isInterrupted()){
// 料理后事,释放资源...
break;
}
// code here...
try{
Thread.sleep(1000);
}catch (InterruptedException e){
// 重新将标识改为true
curThread.interrupt();
}
}
});
t1.start();
// code here...
t1.interrupted();
}
当然,将 “料理后事” 的代码块抽离出来作为方法也是可以的,若休眠时被打断,直接调用该方法并终止也行,就像这样:
private static void releaseResource(){
// 料理后事,释放资源...
}
private static void test(){
Thread t1 = new Thread(() -> {
Thread curThread = Thread.currentThread();
while (true){
if (curThread.isInterrupted()){
releaseResource();
break;
}
// code here...
try{
Thread.sleep(1000);
}catch (InterruptedException e){
// 不改标识,直接调用方法也可以
releaseResouece();
break;
}
}
});
t1.start();
// code here...
t1.interrupted();
}
3. 代码示例
参考资料
[文章] Two Phase Termination 设计模式:两阶段终止模式
[视频] 03.028-设计模式-两阶段终止-interrupt
[视频] 03.029-设计模式-两阶段终止-interrupt-分析
[视频] 03.030-设计模式-两阶段终止-interrupt-实现
[视频] 03.031-设计模式-两阶段终止-interrupt-细节