Java没有提供不论什么机制来安全地(抢占式方法)终止线程,尽管Thread.stop和suspend等方法提供了这种机制,可是因为存在着一些严重的缺陷,因此应该避免使用。
但它提供了中断Interruption机制,这是一种协作机制,可以使一个线程终止还有一个线程的当前工作。
一、任务取消
取消操作的原因:
. 用户请求取消
. 有时间限制的操作
. 应用程序事件
. 错误
. 关闭
结束任务的四种方式:
1. run方法运行结束
2. 使用请求关闭标记(比如boolean开关)
3. 使用中断机制
4. 使用Future退出方法
2. 使用请求关闭标记
当运行到并满足条件是使用return退出run方法
变量须要volatile确保变量多线程环境下的可见性。
-样例待填充,没有运行到推断条件就不会退出。所以不是马上退出的办法。
3. 使用中断机制
长处是相对“请求关闭标记”对应更快一些。但也不是马上关闭线程。
void interrupt() 中断线程。
boolean interrupted() 測试当前线程是否已经中断。
boolean isInterrupted() 測试线程是否已经中断。
InterruptedException异常
程序应该对线程中断作出恰当的响应。
// 1 Thread thread = new Thread("interrupt test") { public void run() { for (;;) { doXXX(); if (Thread.interrupted()) { break; } } } }; thread.start(); // 2 Thread thread = new Thread("interrupt test") { public void run() { for (;;) { try { doXXX(); } catch (InterruptedException e) { break; } catch (Exception e) { // handle Exception } } } }; thread.start(); // 3 public void foo() throws InterruptedException { if (Thread.interrupted()) { throw new InterruptedException(); } }
4. 使用Future退出方法
boolean cancel(boolean mayInterruptIfRunning)
试图取消对此任务的运行。
boolean isCancelled()
假设在任务正常完毕前将其取消,则返回 true。
*. 处理不可中断的堵塞
*. 採用newTaskFor来封装费标准的取消
二、停止基于线程的服务
之前的任务取消。主要是涉及怎样关闭单个线程而且都是由创建单个线程的对象来进行关闭操作,可是假设线程不是由对象自己而是由线程池统一创建的线程该怎样处理呢?
1. 使用线程的对象进行关闭 - 当前即使不在对象中创建线程而由线程池创建,这个对象依旧能够关闭线程,这点一定要相信程序猿的破坏能力,仅仅是使用第2种方式更符合封装原则。
2. 使用线程池统一管理 - 假设是使用ExecutorService创建就交由其进行关闭操作。
2. 使用线程池统一管理(关闭ExecutorService)
void shutdown()
启动一次顺序关闭。运行曾经提交的任务,但不接受新任务。
假设已经关闭,则调用没有其它作用。
-- 安全关闭方式。
List<Runnable> shutdownNow()
试图停止全部正在运行的活动任务,暂停处理正在等待的任务。并返回等待运行的任务列表。
无法保证可以停止正在处理的活动运行任务。可是会尽力尝试。比如,通过 Thread.interrupt() 来取消典型的实现。所以不论什么任务无法响应中断都可能永远无法终止。
-- shutdownNow方法的局限性,强制关闭方式。
boolean isShutdown()
boolean isShutdown()假设此运行程序已关闭。则返回 true。
3. “毒丸”对象
仅仅有在生产者消费者的数量都已知的情况下,才干够使用“毒丸”对象。
三、处理非正常的线程终止
Thread.UncaughtExceptionHandler全局的捕获的异常处理。通常在应用中用于异常的统计,收集到这些统计后能够相应用进行异常修复。
四、JVM关闭
1. 关闭钩子
Runtime.getRuntime().addShutdownHook(new Thread()) ;
void addShutdownHook(Thread hook)
注冊新的虚拟机来关闭钩子。
2. 守护线程
希望创建一个线程来运行一些辅助工作。但又不希望这个线程阻碍JVM的关闭。能够使用守护线程。
3. 终结器
避免使用终结器finalize
五、參考资料:
"程序应该对线程中断作出恰当的响应" 摘录自《温绍锦 - Java并发程序设计教程》