并发(4)终结任务

isCancel()来检查任务是否终止,但是某些情况下,任务会突然终止,这是本节的重点话题。

21.4.1装饰性花园

一个仿真程序,花园存在多个入口,通过一个计数器控制进入人数。通过对计数器的增减进行同步,保证计数的准确性。

21.4.2在阻塞时终结

线程具有四个状态:新建(new)、就绪(Runnable)、阻塞(Blocked)、死亡(Dead)。

以在食堂打饭为例,描述四个状态。

1)新建(new):线程创建时,短暂处于这个状态,系统已经分配的资源并执行了初始化。比如刚到食堂,要拿筷子、餐盘。

2)就绪(Runnable):这种状态下,只有调度器把时间片分配给线程,线程就能执行。比如在某个档口排队。

3)阻塞(Blocked):线程虽然能执行,但是某个条件阻塞它执行。比如突然想去厕所,放弃排队,之后继续排队。

4)死亡(Dead):处于死亡或终止状态的线程不可再被调度。比如打完饭了,执行完了。

应该还会有个运行(Running)状态。

进入阻塞状态的原因

1)通过调用sleep(milliseconds)使得任务进入休眠状态,在这种情况下,任务在指定时间内不执行。

2)通过调用wait()使得线程挂起,直到通知(notify()、notifyAll()、signal()、signalAll)后线程才会进入到就绪状态。

3)任务在等待某个输入/输出完成。

4)任务试图在某个对象上调用同步方法,但是对象锁不可用。

21.4.3中断

Thread.interrupt()可以中断被阻塞的任务。调用该方法必须持有Thread的对象。要对可能抛出的异常进行捕获处理,清理资源。

而在线程池中,Executor提供shutdownNow()的方法,可以给当前池中的所有任务发送interrupt()方法调用。如果你想中断线程池中的某个任务,那么在提交任务的时候要用submit(),而不是executor()。submit()会返回一个Future<?>,此时可以调用cancel()方法中断任务。

需要注意的是,虽然中断了任务的执行,但是不能中断正在试图获取synchronized锁或者试图执行IO操作的线程。这种未中断的线程大量存在时会对生产环境造成影响。一种行之有效的解决方案就是在关闭任务的同时关闭其上发生阻塞的底层资源。比如sockectInput.close()。

幸运的是,nio类提供了更人性化的IO中断,被阻塞的nio通道会自动的响应中断。

被互斥所阻塞的任务,可以通过调用interrupt()中断。

21.4.4检查中断

通过调用interrupted()来检查中断状态。

点击去京东购买《Java编程思想(第四版)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值