调用interrupt()会中断线程,但Thread.isInterrupted()返回false

时间:2014-10-17 16:42:02

标签: java multithreading concurrency interrupted-exception interruption

我正在使用以下测试代码测试InterruptedException:

Runnable runMe = new Runnable() {
    @Override
    public void run() {
        for(int i=0; i<6; i++) {
            System.out.println("i = "+i);
            if(i==3) {
                System.out.println("i==3, Thread = " 
                +Thread.currentThread().getId());
                //I invoke interrupt() on the working thread.
                Thread.currentThread().interrupt();
                try {
                    Thread.currentThread().join();
                } catch (InterruptedException e) {
                    //I caught InterruptedException
                    System.out.println(Thread.currentThread().getId() 
                    + " is interrupted!");
                    Thread.currentThread().interrupt();
                }
            }
        }
    }   
};          
Thread workingThread = new Thread(runMe);
workingThread.start();
try {
    workingThread.join();
} catch (InterruptedException e) {
    //Swallow
}
//the following log shows me workingThread.isInterrupted() is false, why?
System.out.println("workingThread(" 
+ workingThread.getId()+") interrupted ? " 
+ workingThread.isInterrupted());

run(),我interrupt()当前工作线程,并抓住了InterruptedException

在主线程中,我的最后一行代码是System.out.println(...),它打印出工作线程的中断状态。由于我在InterruptedException中抓住了run(),我虽然应该收到workingThread.isInterrupted() true 的消息,但我弄错了,为什么?< /强>

2 个答案:

答案 0 :(得分:4)

Oracle的Java concurrency tutorial说(我强调补充):

  

中断状态标志

     

使用称为中断状态的内部标志实现中断机制。调用Thread.interrupt设置此标志。当线程通过调用静态方法Thread.interrupted来检查中断时,将清除中断状态。非静态isInterrupted方法,一个线程用来查询另一个线程的中断状态,不会改变中断状态标志。

     

按照惯例,通过抛出InterruptedException退出的任何方法都会在执行此操作时清除中断状态。但是,通过另一个调用中断的线程,总是可以立即再次设置中断状态。

你看到的是线程被中断,退出的方法是连接(实际连接是通过调用Object.wait来实现的,所以我希望stacktrace会显示wait是引发异常的方法来自),并且标志会像教程所说的那样被清除。

由异常的处理程序决定是否应该再次设置线程的中断状态标志。除非处理程序被编码为执行不同的操作,否则默认的假设是处理异常并且不再需要设置标志。

API documentation for Thread#interrupt与此一致:

  

如果在调用Object类的wait(),wait(long)或wait(long,int)方法,或者join(),join(long),join(long)时阻塞了这个线程,int),sleep(long)或sleep(long,int),这个类的方法,然后它的中断状态将被清除,它将收到InterruptedException。

我的答案更多地说明了为什么设计中断的原因here

答案 1 :(得分:0)

Runnable runMe = new Runnable() {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("i = " + i);
            if (i == 3) {
                System.out.println("i==3, Thread = "
                        + Thread.currentThread().getId());
                //I invoke interrupt() on the working thread.
                Thread.currentThread().interrupt();
                try {
                    Thread.currentThread().join();
                } catch (InterruptedException e) {
                    //I caught InterruptedException
                    System.out.println(Thread.currentThread().getId()
                            + " is interrupted!");
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
};
Thread workingThread = new Thread(runMe);
workingThread.start();
Thread.sleep(1);
// output true, because child thread not deaded
System.out.println("workingThread("
        + workingThread.getId() + ") interrupted ? "
        + workingThread.isInterrupted());