当前位置: 首页 > Thinking in Java > 正文

第21章 – 并发 – 线程阻塞,线程中断,何时以及如何响应中断

第21章 – 并发 – 线程阻塞,线程中断,何时以及如何响应中断

 

1.在线程阻塞时中断

 

  线程的4中状态:

  (1) 新建(new):线程被创建时,它只会短暂的处于这种状态.

      此时线程已经分配了必须的系统资源,并执行了初始化.

      此刻线程已经有资格获取CPU时间,之后调度器将把这个线程转变为可运行状态

      或阻塞状态

  (2) 就绪(Runnable):在这种状态下,只要调度器把时间片分配给线程,线程就可以运行.

      也就是说,在任意时刻线程可以运行也可以不运行.只要调度器能分配时间片给线程,

      它就可以运行,这不同于阻塞和死亡状态.

  (3) 阻塞(Blocked): 线程能够运行,但有某个条件阻止它运行.当线程处于阻塞状态时,

      调度器将忽略该线程,不会分配给线程任何CPU时间.直到线程重新进入了就绪状态,

      它才有可能执行操作.

  (4) 处于死亡或终止状态的线程将不再是可调度的,并且也不会得到CPU时间,它的任务

      已结束,或不再是可运行的.任务死亡的通常方式是从run()方法返回,但任务的线程

      还可以被中断.

 

  任务进入阻塞状态的4个原因:

  (1) 通过调用sleep(milliseconds)使任务进入休眠状态,此时,任务在指定的时间内不会运行

  (2) 通过调用wait()是线程挂起,直到线程得到了notify()或notifyAll()消息(或signal(),

  signalAll()消息),线程才会进入就绪状态

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

  (4) 任务视图在某个对象上调用其同步控制方法,但是对象的锁不可用,因为另一个任务已经

      获取了锁.

 

  另,在当前现场上调用其他线程的join()方法时,也会引起当前线程阻塞(Java并发编程实践(童云兰等译)P115).

 

2. sleep()造成的线程阻塞可以中断,而IO和synchronized造成的阻塞不可中断(即不能响应中断请求)

 

 

   中断 不可中断阻塞 的方法: 关闭在其上发生阻塞的底层资源.比如 IO阻塞时不可中断,

   在关闭这个IO时便可以中断.

 

   nio类库中的IO阻塞时会自动响应中断.

 

   在ReentrantLock上阻塞的任务具备可被中断的能力.

 

3. 线程的interrupted( )方法检查线程是否被中断,但是该调用同时会清除中断状态.

   因此重复调用该方法不能保证得到相同的值.

 

4. 何时以及如何响应中断?

 

   要中断某个线程,就调用这个线程的interrupt()方法.

   调用interrupt()方法方法并不意味着立即停止目标线程正在进行的工作,而只是传递了请求中断的消息.

   调用该方法后,中断只能在任务将要进入到阻塞操作中,或者任务已经在阻塞操作内部.(P701)

 

   如果调用interrupt()方法时,线程没有阻塞则无能为力(不能使线程中断).

   如下面的示例代码:

 上面代码的改善:在run()方法中检查当前线程的中断状态

 

可中断的阻塞,对中断的响应方式:提前返回,清除中断状态,抛出InterruptedException异常.

比如,Thread.sleep()或BlockingQueue.put().

注意,这里的清除中断状态,当代码中检测InterruptedException时,无法向上层抛出InterruptedException时,

应当在catch到这个异常中重新调用Thread.currentThread.interrupt();

 

所以,run()方法中通常的结构为:

 

更合理的方式:

上面while(!Thread.currentThread.isInterrupted())循环中代码假如有个操作在响应中断时,

先清除中断状态,并抛出InterruptedException异常,则Thread.currentThread.isInterrupted() 

变成false了(因为中断状态在抛出异常中被清除了),那么while循环中检测的条件就不再可靠了

(此时因为抛出异常而将程序执行点已转到catch(InterruptedException e)中,所以还是要使用检测

InterruptedException异常的方式更为可靠).

 

下面是一种合理方式,中断抛出的InterruptedException异常不能被向上传递时,恢复中断状态,

没有使用while(!Thread.currentThread.isInterrupted())

并使用一个变量保存中断信息,使得finally中总是可以恢复中断状态.(Java并发编程实战P118)

 

参考 Java 并发之线程中断 http://my.oschina.net/lifany/blog/163153 

 

5. 处理不可中断阻塞

 

   不可中断阻塞,要实现中断需要关闭当前正在阻塞的资源.

 

打个赏呗

   微信打赏  支付宝打赏


本文固定链接: https://www.jack-yin.com/coding/thinking-in-java/2142.html | 边城网事

该日志由 边城网事 于2015年03月18日发表在 Thinking in Java 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: 第21章 – 并发 – 线程阻塞,线程中断,何时以及如何响应中断 | 边城网事
关键字: ,

第21章 – 并发 – 线程阻塞,线程中断,何时以及如何响应中断 暂无评论

发表评论

快捷键:Ctrl+Enter