2010-08-08 15:04:11| 分类: Java | 标签:线程 中断 java |字号大中小 订阅
thinking in java里对线程中断有一节的讲述,但对程序执行流程总是不明白,上网找到些好文章,基本解决了心中的疑惑。
一、没有任何语言方面的需求一个被中断的线程应该终止。中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断。
我一直都以为调了thread.interrupt()后,线程就立刻停止(类似已被废弃的stop函数),如果真的这样,那会让尚未处理完的数据和状态处于不可知的情况,容易导致不可预计的问题。interrupt更像一个通知,将Thead里的中断标志位设为true,而线程能否退出,就看用户的代码对于这个通知是怎么处理的了。
二、对于处于sleep,join等操作的线程,如果被调用interrupt()后,会抛出InterruptedException,然后线程的中断标志位会由true重置为false,因为线程为了处理异常已经重新处于就绪状态。
我在运行thinking in java里中断的例子时,一直都很奇怪为什么在catch(InterruptedException e)的处理段里,thead.isInterrupted()返回的都是false,原来是已被重置。
三、循环任务线程的中断
1、任务类里做一个信号变量boolean isStopped。循环每次都检查信号量,如果外部逻辑将isStopped设为true,则线程退出。
2、利用线程类已有的信号量isInterrupted。由于sleep、join、wait等操作会抛出中断异常,然后中断标志会被紧接着重置,所以需要做好异常处理。有两种推荐的编码结构:
- public void run() {
- try {
- ...
- /*
- * 不管循环里是否调用过线程阻塞的方法如sleep、join、wait,这里还是需要加上
- * !Thread.currentThread().isInterrupted()条件,虽然抛出异常后退出了循环,显
- * 得用阻塞的情况下是多余的,但如果调用了阻塞方法但没有阻塞时,这样会更安全、更及时。
- */
- while (!Thread.currentThread().isInterrupted()&& more work to do) {
- do more work
- }
- } catch (InterruptedException e) {
- //线程在wait或sleep期间被中断了
- } finally {
- //线程结束前做一些清理工作
- }
- }
- public void run() {
- while (!Thread.currentThread().isInterrupted()&& more work to do) {
- try {
- ...
- sleep(delay);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();//重新设置中断标示
- }
- }
- }
四、不可中断的操作,包括进入synchronized段以及Lock.lock(),inputSteam.read()等,调用interrupt()对于这几个问题无效,因为它们都不抛出中断异常。如果拿不到资源,它们会无限期阻塞下去。
对于Lock.lock(),可以改用Lock.lockInterruptibly(),可被中断的加锁操作,它可以抛出中断异常。等同于等待时间无限长的Lock.tryLock(long time, TimeUnit unit)。
对于inputStream等资源,有些(实现了interruptibleChannel接口)可以通过close()方法将资源关闭,对应的阻塞也会被放开。
而常见的synchronized段死锁的话,还没有看到解决方法。
推荐文章: