论坛首页 Java企业应用论坛

对Java多线程中的InterruptedException的理解

浏览 3742 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-05-06   最后修改:2013-05-06
最近看《Java Concurrency in Practice》,对于线程中断有了更深的理解,不过可能还是不够彻底,也有些疑问,希望可以跟大家讨论下。
之前的时候,如果想在某个线程还在运行的时候终止它,我们一般的做法是先定义一个标志位,然后在线程的run方法中轮训这个标志位,其他线程想要终止这个线程,可以调用cancel方法设置这个标志位为true:
public void run() {  
        BigInteger p = BigInteger.ONE;  
        while (!cancelled) {  
            p = p.nextProbablePrime();  
            synchronized (this) {  
                primes.add(p);  
            }  
        }  
    }  
  
    public void cancel() {  
        cancelled = true;  
    }


在Java的API或语言规范中,并没有将中断与任何语义关联起来,但实际上,如果在取消之外的其他操作中使用中断,那么都是不合适的,并且很难支撑起更大的应用。

Thread中的三个方法:
public void interrupt()   中断一个线程
public boolean isInterrupted()  获取中断标志,判断是否中断
public static boolean interrupted()  清楚中断状态,并返回它之前的状态值

线程在阻塞状态下发生中断的时候会抛出InterruptedException,例如Thread.sleep(), Thread.wait(), Thread.join()等方法。
当线程在非阻塞状态下中断的时候,它的中断状态将被设置,然后根据检查中断状态来判断是否中断。

调用interrupt并不意味着立即停止目标线程正在进行的工作,而只是传递了请求中断的消息,换句话说,仅仅修改了线程的isInterrupted标志字段。

只有实现了线程中断策略的代码才可以屏蔽中断请求,在常规任务和库代码中都不应该屏蔽中断请求。
两种方法响应中断:
* 传递异常InterruptedException
* 恢复中断状态,从而使调用栈中上层代码能够对其进行处理

public void run() {  
        try {  
            BigInteger p = BigInteger.ONE;  
            while (!Thread.currentThread().isInterrupted())  
                queue.put(p = p.nextProbablePrime());  
        } catch (InterruptedException consumed) {  
            /* Allow thread to exit */  
        }  
    }  
  
    public void cancel() {  
        interrupt();  
    }


这个就是大体上我对线程中断的一些总结。

但接下来,我看了下JDK里面的Thread类,里面抛出中断异常InterruptedException都是些native方法,并没有哪些具体的实现方法,具体是怎么跑出来的,比如:
public static native void sleep(long millis) throws InterruptedException;


那么是不是就是说只能是JDK里面定义好的几种方法可以利用InterruptedException去响应中断,而我们自己是不能自定义方法抛出这个InterruptedException的呢? 我们自定义方法只能通过上述检查中断标志的方法去响应中断请求呢?

希望各位能不吝赐教,给予指点。

   发表时间:2013-05-10  
http://ifeve.com/cancellation/?#interruption

遇到中断,一般做下面两件事之一:

1、将自己的方法声明为抛出InterruptedException,不截获到其它方法抛出的中断,将该中断继续上抛(或截获做些处理,再抛出一个InterruptedException);或者检测到中断状态,通过interrupted清除中断状态,然后抛出一个InterruptedException。

2、如果自己的方法无法声明抛出InterruptedException,比如实现某个父类的方法,而父类方法没有声明抛出的异常。这个时候如果遇到其他方法抛出的中断,应该截获该中断,并调用interrupt重新设置中断;如果自己检测并清除了中断状态,在处理完中断逻辑后,也要重新设置中断状态。
0 请登录后投票
   发表时间:2013-05-10  
ticmy 写道
http://ifeve.com/cancellation/?#interruption

遇到中断,一般做下面两件事之一:

1、将自己的方法声明为抛出InterruptedException,不截获到其它方法抛出的中断,将该中断继续上抛(或截获做些处理,再抛出一个InterruptedException);或者检测到中断状态,通过interrupted清除中断状态,然后抛出一个InterruptedException。

2、如果自己的方法无法声明抛出InterruptedException,比如实现某个父类的方法,而父类方法没有声明抛出的异常。这个时候如果遇到其他方法抛出的中断,应该截获该中断,并调用interrupt重新设置中断;如果自己检测并清除了中断状态,在处理完中断逻辑后,也要重新设置中断状态。


如果自己检测并清除了中断状态,在处理完中断逻辑后,也要重新设置中断状态。

这句话不是很理解,自己检测并清除了中断状态,为什么还要重新设置中断状态? 清楚中断状态 跟 重新设置中断状态 不都是将他的中断标志变成false么
0 请登录后投票
   发表时间:2013-05-12  
yidao620c 写道
ticmy 写道
http://ifeve.com/cancellation/?#interruption

遇到中断,一般做下面两件事之一:

1、将自己的方法声明为抛出InterruptedException,不截获到其它方法抛出的中断,将该中断继续上抛(或截获做些处理,再抛出一个InterruptedException);或者检测到中断状态,通过interrupted清除中断状态,然后抛出一个InterruptedException。

2、如果自己的方法无法声明抛出InterruptedException,比如实现某个父类的方法,而父类方法没有声明抛出的异常。这个时候如果遇到其他方法抛出的中断,应该截获该中断,并调用interrupt重新设置中断;如果自己检测并清除了中断状态,在处理完中断逻辑后,也要重新设置中断状态。


如果自己检测并清除了中断状态,在处理完中断逻辑后,也要重新设置中断状态。

这句话不是很理解,自己检测并清除了中断状态,为什么还要重新设置中断状态? 清楚中断状态 跟 重新设置中断状态 不都是将他的中断标志变成false么

重设中断状态是因为方法无法抛出InterruptedException,为什么要重设?假设你的方法是封装给别人调用的,别人自己也想通过中断来处理一些事情,但他不知道你在方法里把中断给清除掉了,那他就悲剧了。所以只有把中断状态重新设置为true,他就能检测到并做他想做的事情。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics