Java 多线程设计模式之Two-phase Termination

Two-phase Termination 模式通过将停止线程这个动作分解为准备阶段和执行阶段这两个阶段,提供了一种通用的用于优雅地停止线程的方法。所谓优雅是指可以等要停止的线程在其处理完待处理的任务后停止,而并不是强行停止。
准备阶段

该阶段的主要动作是“通知” 目标线程(欲停止的线程)准备进行停止。这一步会设置一个标志变量用于指示目标线程可以准备停止了。
能够对Thread.interrupt 做出响应的一些方法

方法响应interrupt 调用抛出的异常
Object.wait()、Object.wait(long timeout)、Object.wait(long timeout, int nanos)InterruptedException
Thread.sleep(long millis)/Thread.sleep(long millis,int nanos)InerruptedException
Thread.join()、Thread.join(long mills、Thread.Join(long millis, int nanos)InerruptedException
java.util.concurent.BlockingQueue.take()InterruptedException
java.util.concurrent.locks.Lock.lockInterruptibly()InterruptedException
java.nio.channels.InterruptibleChanneljava.nio.channels.ClosedByInterruptException
执行阶段

该阶段的主要动作是检查准备阶段所设置的线程停止标志和信号,在此基础上决定线程停止的时机,并进行适当的“清理”操作。

toShutdown 这个变量为了保证内存的可见性而又能避免使用显式锁的开销,而采用了volatile 修饰。若采用boolean 作为线程停止标志的代码,只是这些变量没有volatile 修饰,对其访问也没有加锁,这就可能无法停止目标线程。

另外,某些场景下多个可停止线程实例可能需要共用一个线程停止标志。例如,多个可停止线程实例“消耗”同一个队列中的数据。当该队列为空且不再有新的数据入队列的时候,“消耗”该队列数据的可停止线程都应该被停掉。
AbstractTerminatableTread 类的构造器支持传入一个TerminationToken 实例就是为了支持这种场景。

java.util.concurrent.ThreadPoolExecutor 就使用了Two-phase termination 模式来停止其内部维护的工作者线程。ThreadPoolExecutor 实例的停止过程也是分为准备阶段(设置其运行状态为SHUTDOWN) 和执行阶段(工作者队列取空工作队列中的任务,然后终止线程)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值