【问题标题】:Why invoke Thread.currentThread.interrupt() in a catch InterruptException block?为什么在 catch InterruptException 块中调用 Thread.currentThread.interrupt()?
【发布时间】:2011-06-21 20:44:43
【问题描述】:

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

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    这样做是为了保持状态

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

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

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

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

    【讨论】:

    • documentation 中声明“按照惯例,任何通过抛出InterruptedException 退出的方法在这样做时都会清除中断状态 我认为这使得为什么您需要保留中断状态的答案更加清晰。
    • 还值得注意的是,一旦您通过其他“传递机制”(@ 987654327@ 并希望或不能重新抛出它。
    • higher-level methods/thread groups 是什么意思?
    【解决方案2】:

    我认为这个代码示例让事情变得更清楚了。 完成这项工作的班级:

    public class InterruptedSleepingRunner implements Runnable {
        @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) {
                Thread.currentThread().interrupt();
            }
        }
    }
    

    Main 类:

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

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

    【讨论】:

    • 所以结论是??
    • 谢谢。我明白你现在的意思了:repl.it/@djangofan/InterruptedThreadExample
    • 我认为他的意思是Thread.currentThread().interrupt(); 允许您更快地退出线程,因此当InterruptedException e 被捕获时,线程会在那里停止。而如果不使用Thread.currentThread().interrupt();,线程会继续执行..
    【解决方案3】:

    注意:

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

    如何停止长时间等待(例如,等待输入)的线程?

    要使这项技术发挥作用,任何捕获中断异常但不准备处理它的方法都必须立即重新声明异常。我们说重新断言而不是重新抛出,因为并不总是可以重新抛出异常。 如果捕获 InterruptedException 的方法未声明抛出此(已检查)异常,则应使用以下咒语“重新中断自身”:

    Thread.currentThread().interrupt();
    

    这确保线程将尽快重新引发 InterruptedException。

    【讨论】:

      【解决方案4】:

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

      Thread.currentThread.interrupt() 的唯一理由是你真的什么都做不了除了finally 块中的例外情况。

      如果您想更好地了解 Thread.currentThread.interrupt() 调用的含义,请参阅 Péter Török 的回答。

      【讨论】:

        【解决方案5】:

        参考java文档

        如果该线程在调用 wait()、join() 时被阻塞, sleep(long),则其中断状态将被清除,它会 收到一个 InterruptedException。

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

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

        如果前面的条件都不成立,那么这个线程的中断 状态将被设置。

        因此,如果您将@Ajay George Answer 中的 sleepBabySleep() 方法更改为 I/O 操作或只是一个 sysout,则无需将状态设置回停止程序。 (顺便说一句,他们甚至不抛出 InterruptedException)

        就像@Péter Török 所说 => 这样做是为了保持状态。 (特别是对于会抛出 InterruptedException 的方法)

        【讨论】:

          猜你喜欢
          • 2023-03-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-05
          • 2019-05-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多