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

任务的取消:

可能会有多种原因导致任务取消:超时、用户显示停止、错误、事件触发、关闭

java里没有显示定义如何抢占式地关闭一个线程,任务的取消需要任务自己定义一套协议,比如简单地定义是否取消变量,在run方法中不停检查这个变量。外部发起取消命令的时候改变这个变量。

中断:

上面说的取消策略并不完美,因为run里面可能调用阻塞的方法,从而可能根本没机会退出阻塞方法来查看取消变量。

非常多的阻塞方法都能响应中断,在收到中断命令的时候抛出InterruptedException从而立即退出,如果任务支持取消,且run中调用的阻塞方法,建议catch interrupted Exception从而利用中断来取消任务。

java中的中断的作用就是取消使用的,没有别的场景使用中断。每个thread对象有中断的相关函数

通过future取消任务

如果需要支持超时,一种解决方法是拿到future后,在future.get函数里设置超时方法,如果超时了,会调用cancel取消任务

处理不可中断的阻塞

当任务中调用了不可中断的阻塞方法时,如socket io,同步io,锁,如果需要支持实时取消任务,则需要在取消处理函数里关闭socket,关闭文件IO句柄等一系列可以强制阻塞方法退出的函数。

java6的excutor添加了newTaskFor接口,可以覆盖这个方法,来返回自定义的future,自定义的future可以自定义cancel处理。

停止基于线程的服务

一个服务可能拥有多个线程,比如日志服务接收log调用,后台用多线程去刷写日志。如果需要停止一个服务,需要内部停止服务的所有线程,需要告知服务调用者服务已停止

excutor service的关闭

excutorservice支持shutdown和shutdownnow,shotdown会等到所有线程执行完关闭,shutdownnow会立即返回未执行的线程,并发送cancel命令到正在执行的线程,如果需要获取正在执行被cancel的任务,需要手动定制cancel的处理,保存当前的任务信息。

典型做法是在全局启动excutor service,并发送所有任务,在关闭前调用shutdown,和awaittermination来等待任务结束

处理非正常线程的终止

线程抛runtimeexception时,有集中做法来处理异常。1. 线程池里的线程遇到异常后,会停止运行,在退出前会保存异常到线程变量里,GC在回收一个线程,如果有未处理的异常,则会调用UncaughtExceptionHandler处理,可以在这个钩子里处理异常。调用Future.get方法时,如果线程有异常,也会抛出来这个异常

JVM关闭

JVM提供了关闭钩子,可以在关闭钩子里做资源清理等事情。因为所有关闭钩子是并行运行的,所以最好不要在关闭钩子里依赖其他关闭钩子可能停止的服务,因为此时服务可能已经关闭,最好将所有服务在同一个关闭钩子函数里运行

猜你喜欢

转载自blog.csdn.net/xuefeiliuyuxiu/article/details/80254424