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

时间:2011-02-05 12:25:35

标签: java multithreading interrupt

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

5 个答案:

答案 0 :(得分:140)

这是为了保持状态

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

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

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

  

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

答案 1 :(得分:57)

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

   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();
        }

    }

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

答案 2 :(得分:20)

注意:

http://download.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

如何停止等待很长时间的话题(例如输入)?

  

要使这项技术起作用,任何捕获中断异常并且不准备立即处理它的方法都必须重新确认异常。我们说重申而不是重新抛出,因为并不总是可以重新抛出异常。 如果没有声明捕获InterruptedException的方法抛出此(已检查)异常,那么它应该使用以下咒语“重新中断”:

Thread.currentThread().interrupt();

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

答案 3 :(得分:2)

我认为这是一种不好的做法,或者至少有点冒险。 通常,更高级别的方法不执行阻塞操作,并且永远不会在那里看到InterruptedException。如果你在每个地方掩饰你进行可中断的操作,你就永远无法得到它。

Thread.currentThread.interrupt()的唯一理由,而不是以任何其他方式引发任何其他异常或信令中断请求(例如,在线程的主循环中设置interrupted局部变量变量)是你真的可以的情况除了finally块之外,不对异常做任何事情。

如果您想更好地理解Thread.currentThread.interrupt()电话的含义,请参阅PéterTörök的答案。

答案 4 :(得分:0)

从Java文档引用

如果在调用wait(),join(), 睡眠(长),然后其中断状态将被清除,并且它将 收到InterruptedException。

如果此线程在I / O操作中被阻塞,则该线程的中断 状态将被设置,线程将收到一个 ClosedByInterruptException。

如果此线程在选择器中被阻止,则该线程的中断 状态将被设置,它将立即从选择中返回 操作。

如果先前的条件均不成立,则此线程的中断 状态将被设置。

因此,如果您在@Ajay George Answers中更改I / O操作的sleepBabySleep()方法或仅更改为sysout,则不必将状态重新设置为停止程序。 (顺便说一句,他们甚至没有抛出InterruptedException)

就像@PéterTörök所说的=>这样做是为了保持状态。 (特别是将引发InterruptedException的方法)