纷享InterruptedException 应该如何处理? 2019-07-04
以下代码Java编程中经常会遇到,sleep 会抛出一个 InterruptedException 表示当前线程被其他线程中断。那这种处理 InterruptedException 的方式是否合理呢?
|
|
阻塞方法
如果一个方法会抛出 InterruptedException,表明当前方法是一个阻塞方法,同时这个方法可以尝试结束阻塞并提前返回。阻塞方法的执行,依赖外部条件,例如超时、I/O完成或其他线程的某个动作(释放锁、某个状态值满足条件等)。阻塞方法事实上可以永久地等待某个条件发生,所以需要能提前结束或取消。Thread.sleep() 和 Object.wait() 支持抛出 InterruptedException ,如果抛出该异常表明当前线程被中断,可以提前结束或取消。
处理 InterruptedException
最简单的方式是将 InterruptedException 抛出,由上层调用者决定如何处理。
有的场景可能需要在抛出 InterruptedException 后做一些后续工作,这样就需要在当前线程捕获该异常,并在 catch 块中完成后续工作,最后在将异常重新抛出。
不要直接「吃掉」 InterruptedException
以下场景是我们经常遇到的:
|
|
一个线程内部会抛出 InterruptedException ,但无法向外抛出。此时需要在捕获异常之后,设置当前线程的中断状态,即调用 Thread.currentThread().interrupt() 。这样调用栈上能够处理该异常的方法就会对该状态做出响应。
捕获到 InterruptedException 后最坏的做法就是直接「吃掉」,即便已经记录日志。标准线程池(ThreadPoolExecutor)针对线程中断有专门的处理,这样线程池中的线程就能响应「取消任务」、「线程池关闭」等中断请求。
不可中断的阻塞方法
并不是所有的阻塞方法都能够响应中断。例如input 和 output stream 会阻塞等待 I/O 完成。阻塞发生在 synchronized 代码块,也无法中断。
无法取消的任务
以下场景,不允许中断任务的执行,然而这种情况下,也需要保存任务的中断状态,这样在方法调用返回的时候能够保存中断状态,供调用方做处理。
|
|
总结
利用中断机制可以实现灵活的取消策略来响应中断,线程可以决定任务取消与否,并进行相关的清理工作。如果当前方法忽略中断,那确保中断状态能重新抛出给上层调用方。