任务取消
中断
不可靠的取消操作将把生产者至于阻塞的操作中<br>如果生产者的速度超过消费者, 并且队列北填满, put方法也会被阻塞, 可能这个方法永远不会被终止
阻塞库方法, 都会检查线程何时中断,并且在发现中断时提前返回
通常, 中断是实现取消的最合理方式
中断策略
最合理的中断策略是某种形式的线程级取消操作或服务级取消操作: 尽快退出,在必要时进行清理, 通知某个所有者该线程已退出\
如果出了将InterruptedExcpetion传递给调用者之外还需要执行其他操作,那么应该在捕获异常后恢复中断状态<br>Thread.currentThread().interrupt();
响应中断
有2种策略可以用于处理InterruptedException
传递异常, 从而使你的方法也成为可中断的阻塞方法
恢复中断状态,从而使调用栈种的上层代码能够对其进行处理
计时运行
许多问题永远无法解决,如果能指定"最多花10分钟搜索答案"或者"枚举出在10分钟累哦能找到的答案", 那么则需要计时运行
在外部线程中安排中断<br>由于timedRun可以从任意一个线程调用,因此它无法知道这个调用线程的中断策略
这个示例的代码解决了前面示例中的问题,但由于它以来于一个限时的join,因此存在join的不足: 无法知道执行控制是因为线程正常退出而返回还是因为join超时返回
通过Future来实现取消
当Futrue.get抛出InterruptException或TimeoutException, 如果你知道不再需要结果,那么就可以调用Future.cancel来取消
停止基于线程的服务
示例:日志服务
不支持关闭的生产者-消费者日志服务<br>这种直接关闭的方式,会丢失那些正在等待被写入到日志的信息
通过一种不可靠的方式为日志服务增加关闭支持<br>设置某个"已请求关闭"标志,以避免进一步提交日志消息, 但是这样有概率使线程阻塞在put方法,并无法解除阻塞
向LogWriter添加可靠的取消操作
关闭ExecutorService
ExecutorService会一直等到队列中的所有任务都执行完成后才关闭
毒丸对象
当得到这个对象时,立即停止
通过"毒丸"对象关闭服务
处理非正常的线程终止
我们都需要在任何时候考虑捕获RuntimeException
典型的线程池工作者线程结构<br>如果检查到异常,那么它将使线程终结,但会首先通知框架该线程已经终结<br>
只有通过execute提交的任务,才能抛出异常, 而submit提交的任务的异常被认为是返回状态的一部分
JVM关闭
关闭钩子
指通过Runtime.addShutdownHook注册的但尚未开始的线程
通过注册一个关闭钩子来停止日志服务
守护线程
JVM启动时创建的所有线程中,除了主线程以外,其他的线程都是守护线程
我们应该尽可能少地使用守护线程, 例如守护线程中执行可能包含I/O操作的任务, 那么将是危险的
守护线程最好用于执行"内部"任务,例如周期性地从内存的缓存中移除逾期的数据
终结器
一些资源,如文件句柄,套接字句柄,当不需要他们时,必须显式交换给操作系统
垃圾回收期对定义了finalize方法的对象进行特殊处理
避免使用终结器