Java中原来在Thread中提供了
stop()方法
来终止线程,但这个方法是不安全的,因此通常不建议使用。文本将介绍两种能够优雅的终止线程的方式...java
<!-- more -->git
在JAVA《Java多线程模式》
中有一种叫Two-Phase Termination(两步终止)的模式
能够优雅的终止线程,这种模式采用了两个步骤来终止线程,因此叫两步终止模式
。安全
isShutdown
设为false
,使工做中的线程转变为终止处理
中的状态class Worker extends Thread { private volatile boolean isShutdown = true; public void shutdown() { System.out.println("接收到关闭通知......"); this.isShutdown = false; interrupt(); } @Override public void run() { while (this.isShutdown) { System.out.println("正在工做:" + System.currentTimeMillis()); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("打断正在工做的线程......"); } } System.out.println("销毁......"); } } public class ThreadClose { public static void main(String[] args) throws InterruptedException { Worker worker = new Worker(); worker.start();//开始工做 Thread.sleep(3 * 1000); worker.shutdown();//优雅关闭 } }
运行日志微信
正在工做:1505828036769 正在工做:1505828037770 正在工做:1505828038771 接收到关闭通知...... 打断正在工做的线程...... 销毁......
--Critical Section
的时候忽然结束掉shutdown()
中,会调用interrupt()
,保证即便线程处于sleep
或wait
状态也能够被当即终止isShutdown
设为volatile
,能保证线程收到终止请求后,会尽快开始终止处理。存在的问题:针对没有阻塞的状况:设置标志变量,让线程正常天然死亡,和谐!,可是若是在调用shutdown
发生阻塞状况呢?多线程
在 《多线程第一章》的时候,介绍过守护线程
的做用,那么是否是能够经过开启守护线程
的方式去监听ide
1.当工做结束就关闭主线程(主线程销毁守护线程也会跟着一同销毁)
2.若是任务长时间未完成,中止工做任务,减小开销测试
1.定义主线程与发送的指令
2.在主线程run
方法中建立一个守护线程,用来执行咱们投递的任务
3.前面已经介绍过join
的功能,它能够阻塞主线程,等待子线程完成后主线程继续执行
4.若是join
释放后,发送完成指令this
private Thread executeService; private volatile boolean finished = false; public void execute(Runnable task) { executeService = new Thread(() -> { Thread runner = new Thread(task); runner.setDaemon(true); runner.start(); try { runner.join();//前面已经说过join与线程了 finished = true; } catch (InterruptedException e) { System.out.println("打断正在工做的线程......"); } }); executeService.start(); }
5.建立listener(long mills)
,监听工做状况
6.监放任务是否完成,若是未完成监听当前是否逾期,逾期打断线程结束监听编码
public void listener(long mills) { System.out.println("开启监听......"); long currentTime = System.currentTimeMillis(); while (!finished) { if ((System.currentTimeMillis() - currentTime) >= mills) { System.out.println("工做耗时过长,开始打断..."); executeService.interrupt();//打断线程 break; } try { executeService.sleep(100L);//每隔100毫秒检测一次 } catch (InterruptedException e) { e.printStackTrace(); } } }
7.测试线程
public static void main(String[] args) { WorkerService service = new WorkerService(); long start = System.currentTimeMillis(); service.execute(() -> { try { Thread.sleep(3 * 1000);// TODO 模拟加载数据 } catch (InterruptedException e) { e.printStackTrace(); } }); service.listener(4 * 1000); System.out.println("一共耗时:" + (System.currentTimeMillis() - start)); }
listener(4 * 1000) 的运行日志,当任务完成会直接退出,并不会一直占用
开启监听...... 一共耗时:3049
listener(2 * 1000) 的运行日志,当任务超时直接打断线程,减小资源占用
开启监听...... 工做耗时过长,开始打断... 一共耗时:2050 打断正在工做的线程......
微信公众号:battcn
(欢迎调戏)