为什么在catch InterruptException块中调用Thread.currentThread.interrupt()?

问题

为什么在catch块中调用Thread.currentThread.interrupt()方法?


#1 热门回答(119 赞)

这是维持状态。

当你捕获InterruptException并吞下它时,你基本上阻止任何更高级别的方法/线程组注意到中断。这可能会导致问题。

通过调用Thread.currentThread().interrupt(),你可以设置线程的中断标志,因此更高级别的中断处理程序会注意到它并且可以正确处理它。

Java Concurrency in Practice在第7.1.3节:响应中断时更详细地讨论了这一点。它的规则是:

只有实现线程中断策略的代码才可以吞下中断请求。通用任务和库代码永远不应吞下中断请求。


#2 热门回答(49 赞)

我认为这个代码示例使事情变得清晰。完成工作的班级:

public class InterruptedSleepingThread extends Thread {

        @Override
        public void run() {
            doAPseudoHeavyWeightJob();
        }

        private void doAPseudoHeavyWeightJob() {
            for (int i=0;i<Integer.MAX_VALUE;i++) {
                //You are kidding me
                System.out.println(i + " " + i*2);
                //Let me sleep <evil grin>
                if(Thread.currentThread().isInterrupted()) {
                    System.out.println("Thread interrupted\n Exiting...");
                    break;
                }else {
                    sleepBabySleep();
                }
            }
        }

        /**
         *
         */
        protected void sleepBabySleep() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                //e.printStackTrace();
                Thread.currentThread().interrupt();
            }
        }
    }

主类:

public class InterruptedSleepingThreadMain {

        /**
         * @param args
         * @throws InterruptedException
         */
        public static void main(String[] args) throws InterruptedException {
            InterruptedSleepingThread thread = new InterruptedSleepingThread();
            thread.start();
            //Giving 10 seconds to finish the job.
            Thread.sleep(10000);
            //Let me interrupt
            thread.interrupt();
        }

    }

尝试在不设置状态的情况下调用中断。


#3 热门回答(16 赞)

注意:
http://download.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html如何停止等待很长时间的线程(例如输入)?>为了使这项技术起作用,任何捕获中断异常并且不准备立即处理它的方法都必须重新确认异常。我们说重申而不是重新抛出,因为并不总是可以重新抛出异常。如果没有声明捕获InterruptedException的方法抛出此(已检查)异常,那么它应该使用以下咒语"重新中断":

Thread.currentThread().interrupt();

这确保了线程能够尽快重新加入InterruptedException。