java并发实战第七章

最近忙着看文档所以一直没有怎么写,今天抽空继续看并发实战的第七章

第七章主要讲解了关于线程任务的取消与关闭,众所周知启动一个任务和线程很容易但是想要提前结束一个任务并不是那么容易,java没有提供安全终止任务的机制,但是却提供了一种中断协作机制,能够使一个线程终止当前另一个线程的工作。

1.任务取消

如果外部代码能在某个操作正常完成之前将其植入完成状态,那么这个操作就是可以取消的,通常来说取消某个操作的原因有以下几个:

①用户请求取消

②有时间限制的操作

③应用程序事件

④错误

⑤关闭

在Java中没有一种安全的抢占式方法停止线程,只有一种协议机制,是请求的代码和取消的任务都遵循一种协商好的机制

其中一种机制能设置好某个已请求取消的标志,任务将定期查看这个标志,如果该标志被设置那么任务终止,可取消的任务必须要拥有可取消的策略

中断

前面曾提过一些特殊的阻塞库方法支持中断。线程中断时一种写作机制,线程可以通过这种机制通知别的线程停止当前工作。其中阻塞库方法例如Thread.sleep和Object.wait()都会检查线程何时中断,并在发现中断时提前返回,他们响应中断的操作包括:清除中断状态,抛出异常。如果线程在非阻塞状态下中断时,他的中断状态将被设置,然后根据被取消的操作来检查是否发生中断,如果不抛出异常,中断将一直保持直到发出信号来清楚中断状态。中断操作并不会真正的中断一个正在运行的线程,他只是发出了中断请求然后收到请求的线程在合适的时候停止自己。使用interrupted方法应该小心,因为他会清楚线程的中断状态。

中断策略

中断策略和取消策略一样是线程已改包含的,中断策略规定线程受到中断请求后应该做哪些工作。合理的中断策略应该是线程级或服务级取消操作:尽快退出并在必要的时候进行清理,通知某个所有者该线程已经退出。此外还可以建立暂停那个服务或重新开始任务等策略。一个中断请求可以有一个或多个接收者。任务不会在自己的线程中执行而是在某个服务级拥有的线程中执行。任务检查到中断请求后并不需要放弃所有操作,他可以推迟处理中断请求,并在合适的时候执行请求,除此之外任务本不应该对执行假设

处理不可中断阻塞

java库中一般都是通过抛出中断异常来响应中断请求,然而并非所有可阻塞方法和阻塞机制可以响应中断。对于这类线程可以采取直接中断的方式

采用newTaskFor封装非标准的取消

newTaskFor可以优化非标准取消的技术,他是Java6的新功能。当Callable把任务交给一个ExecutorService时候返回一个Future,我们可以通过Future来取消任务。newTaskFor是一个工厂方法,他会创建Future来代表任务,他还能返回一个接口,该接口扩展了Future和Runnable。

2.停止基于线程的服务

应用程序通常会创建多个线程服务,通常这些服务的的生命周期比应用程序更长,如果应用程序退出那么他们应该以合理的方式自行结束。正确的做法是为服务提供能服务周期方法这样

②关闭ExecutorService

ExecutorService提供了两种关闭方法,使用shutdown正常关闭以及使用shutdownnow强行关闭,在强行关闭的时候shutDownNow会首先关闭当前执行的任务然后返回所有尚未启动的任务

③毒丸对象

另一种关闭生产者消费者模式的方式就是使用毒丸对象,毒丸是指一个放在队列中的对象,当得到这个对象时立即停止,在先进先出队列中毒丸对象保证消费者在关闭之前完成队列所有任务,毒丸对象只有在生产者和消费者数量都已知的情况下才可以使用

④shutdownNow局限性

当通过shutdownnow命令来强行关闭ExecutorService时,他会尝试取消正在执行的任务,宁返回尚未喀什的任务,然而我们无法知道哪些任务应经开始但是尚未开始

3处理非正常的线程终止

当线程由于发生了一个未捕获的异常终止时程序将停止运行,并产生异常信息。然而某个线程发生异常并不是那么明显。因此必须有用某些方法进行检测,导致线程异常死亡的主要原因是RuntimeException这类异常通常不会被捕获也不会在调用栈中逐层传递,线程遗漏可能是良性的也可能是恶性的,因此应该使用try-catch块来调用任务,这样就能捕获哪些异常了。除此之外ThreadAPI中同样提供了UncaughtExceptionHandler,当一个线程由于未捕获异常而退出时,jvm会把这个报告提供给异常处理器,如果未提供异常处理器默认输出到System.err并主动检测出线程异常终止的情况并将它写入程序日志中。当要为线程池设立异常捕获器,需要为ThreadExecutorPool构造函数提供一个ThreadFactory但是只有通过Execute提交的任务可以将它抛出的异常提供给溢出捕获处理器而submit提交的任务无论是未检查异常还是已检查异常都会被认为任务状态返回的一部分,如果一个由submit提交的任务熬出异常而终止,那么这个异常将封装在ExecutionException中重新抛出

4.jvm关闭

①jvm可以正常关闭也可以强行关闭。正常关闭中jvm调用已注册的shutdown hook。他们是指通过Runtime.addShutDownHook注册的但是尚未开始的线程。jvm并不能保证关闭他们是的调用顺序,再关闭线程时如果有线程正在运行,那么这些线程将与关闭进程并发执行。当所有的shutdown hook结束时,如果runFinalizerOnExit为true那么虚拟机停止运行,当jvm结束运行时,并行的线程也会被强行结束如果shutdown hook没有结束或者终结器没有执行完成,那么正常关闭进程挂起并且jvm正常关闭。当关闭jvm时候,shutdown hook不会被关闭

②守护线程

用来进行辅助工作并且不会影响主线程工作的线程,守护线程在主线程进行完工作时将会被自动抛弃

③终结器

当并不需要资源时,可以通过垃圾回收器来回收他们,但对于其他一些资源当不需要他们时必须显示的交还给操作系统,对于实现这种功能,垃圾回收器会对那些定义为finalize方法对象进行特殊处理:在回收期释放他们后,调用他们的finalize方法,从而保证持久化的资源被释放。由于终结器可以在某个有jvm管理的线程中运行,因此终结器的任何访问状态可能会被多线程访问,因此必须进行同步,但是这样会产生相当大的开销,通常使用finally和close已经可以很良好的解决问题,所以尽量不要自己编写终结器。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值