Java并发编程实战笔记5:取消与关闭

615 阅读3分钟

任务取消

如果外部代码能在某个操作正常完成之前将其置入“完成”状态,那么这么操作就可以称为可取消的。Java中有一些协作式的机制,使得请求取消的任务和代码都遵循一种协商好的协议。

线程中断是一种用于停止线程的协作机制,线程可以通过这种机制来通知另一个线程,告诉它在合适的或者可能的情况下停止当前工作。

每个线程都有一个布尔变量表示其中断状态。使用interrupt()方法将中断状态设置为ture;使用isInterrupted()判断线程的中断状态;使用Thread.interrupted()判断当前线程的中断状态,并将当前线程的中断状态设置为false。

调用interrupt()方法并不意味着立即停止目标线程正在进行的工作,而只是传递了请求中断的消息,然后由线程在合适的时刻中断自己。通常,中断是实现取消的最合理的方式。

当检查到中断请求后,任务并不需要放弃所有的操作,它可以推迟处理中断请求,并直到某个更合适的时候。因此需要记住中断请求,并在完成当前任务后抛出InterruptedException或者表示已经收到中断请求。

响应中断

当调用可中断的阻塞函数时,如Thread.sleep()或者BlokcingQueue.put(),Object.wait()等。可以在别的线程中调用当前线程对象的interrupt方法触发这些函数抛出InterruptedException异常,有两种策略来处理:

  • 传递异常,从而使你的方法也成为可中断的阻塞方法
  • 恢复中断状态,从而使调用栈中的上层代码能够对其进行处理。

当你捕获到InterruptedException异常后,当前线程的中断状态已经被修改为false(表示线程未被中断);此时你若能够处理中断,则不用理会该值;但如果你继续向上抛InterruptedException异常,你需要再次调用interrupt方法,将当前线程的中断状态设为true。

只有实现了线程中断策略的代码才能屏蔽中断请求,不能捕获异常却不做处理。

使用Future实现取消

Future有一个cancel(boolean mayInterruptIfRunning) 方法:该方法是非阻塞的,该方法可以用来(尝试)终止一个任务。

  • 如果任务运行之前调用了该方法,那么任务就不会被运行;
  • 如果任务已经完成或者已经被取消,那么该方法方法不起作用;
  • 如果任务正在运行,并且 cancel 传入参数为 true,那么便会去终止与 Future 关联的任务。

cancel(false) 与 cancel(true)的区别在于,cancel(false)只取消已经提交但还没有被运行的任务(即任务就不会被安排运行);而 cancel(true) 会取消所有已经提交的任务,包括正在等待的和正在运行的任务。

参考资料