【问题标题】:Thread Interrupts. Can someone explain me the output to understand interrupts better? [closed]线程中断。有人可以向我解释输出以更好地理解中断吗? [关闭]
【发布时间】:2015-04-25 11:51:17
【问题描述】:

我能够理解线程和中断。我试图映射从 Oracle 教程中学到的基本概念,以更好地理解中断的概念。我开发了这个例子并努力理解输出是如何在这里发挥作用的。我只是不明白。所以我的想法是请人帮助我理解这个程序的输出,这将使我更清楚地了解中断的底层功能。

public class ThreadSleepTest {
    public static void main(String[] args) throws InterruptedException {
        MyRunnable myRunnable = new MyRunnable();
        Thread one = new Thread(myRunnable);
        one.setName("Fred");
        Thread two = new Thread(myRunnable);
        two.setName("Lucy");
        Thread three = new Thread(myRunnable);
        three.setName("Ricky");
        one.start();
        two.start();
        three.start();
        //Thread.sleep(1000);
        one.interrupt();
     }    
}

class MyRunnable implements Runnable {
    public void run() {
        for (int x = 1; x < 4; x++) {
            System.out.println("Run by: " + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ie) {
                System.out.println("Exception occured");
            }
        }
        System.out.println("Do something");
    }
}

这是我的控制台的输出。

Run by: Lucy
Run by: Fred
Run by: Ricky
Exception occured
Run by: Fred
Run by: Fred
Run by: Lucy
Run by: Ricky
Do something
Run by: Lucy
Run by: Ricky
Do something
Do something

【问题讨论】:

  • 我已阅读并理解,但输出仍然令人困惑。
  • 令人困惑的原因是什么?你期待什么?为什么?
  • @EJP 的建议值得一票!
  • @benz 并发非常棘手。我相信 EJP 的建议是,如果程序的输出让你感到困惑,那么找出什么样的输出会更容易混淆。

标签: java multithreading interrupt interrupted-exception


【解决方案1】:

一旦线程中断,按照我的理解,它基本上是停止运行的。

不,你的理解是错误的。一旦线程被中断,由编写run 方法的程序员决定如何处理它。

线程终止完全取决于程序员,因为 JVM 实际上并不知道在终止线程时可能需要清除哪些资源和锁。这就是为什么 Thread 中的 stop()suspend() 方法已被弃用的原因。它们不安全。

所以当一个线程被中断时,如果你在一个抛出InterruptedException的方法中,你必须对这个异常做出反应并完成你正在做的任何事情,如果你在自己的事情中间,你必须时不时检查当前线程的interrupted()状态,如果发生中断,就完成你正在做的事情。

当你的线程被中断时,你选择执行以下操作:

        try {
            Thread.sleep(1000);
        } catch (InterruptedException ie) {
            System.out.println("Exception occured");
        }

在您的catch 子句中,您只是在打印发生异常的事实。你实际上并没有对线程的终止做任何事情。因此,它不会被终止。您将退出 catch 子句,并继续循环的下一次迭代。

Thread.sleep() 按照惯例在抛出InterruptedException 时会清除中断标志。所以在下一次迭代中,线程不再“中断”,sleep() 也不再抛出异常。

【讨论】:

    【解决方案2】:

    中断线程意味着向它发出信号以停止执行当前正在执行的操作。

    大多数 I/O 和锁定操作将在运行的线程中断并且在该线程中引发 InterruptedException 时中断(但是,并非所有操作都这样做,例如参见 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html#acquireUninterruptibly())。

    然后代码能够以他/她认为合适的任何方式处理异常。在InterruptedException 引发后,中断信号被消耗,线程可以继续做任何事情。在您的示例中,Thread.sleep() 调用较早完成,抛出 InterruptedException 并记录一条消息。之后,线程继续for 循环。当然,线程可以稍后被中断。

    【讨论】:

      【解决方案3】:

      我认为 Java 并发实践 (JCiP),第 138 页对可能发生的情况给出了相当好的解释。您可以注意以下几点:

      • 主线程创建并启动 3 个线程,分别命名为:Fred、Lucy、Ricky。我们只考虑名为 Fred 的线程,它被分配给变量 one(有更好的方法,例如 CountdownLatch)。
      • Fred,在计划运行后立即被您的代码置于睡眠状态。方法Thread.sleep 是一个精心设计的阻塞调用。这意味着它可以通过发送中断来中断。这正是主线程试图做的事情:请求中断one 正在做或不做的任何活动线程(因为在这种情况下它只是在睡觉)。 main 线程只需在 one 上调用 interrupt() 方法即可。请注意,这仅被被中断的线程视为“友好请求”。
      • 在您看到输出“发生异常”的情况下,(休眠的)被中断线程会确认中断,并且如文档所述,会引发 InterruptedException。此异常被one 捕获,并在标准输出上打印消息“发生异常”。因此,主线程成功地中断了one 正在做的事情
      • 其他线程不间断地执行其任务(这就是您看到其他打印语句的原因)。

      【讨论】:

        【解决方案4】:

        如果你中断一个线程,下一次或当前你在这个线程中休眠或等待的时间会抛出一个 InterruptedException。但是中断状态被清除了。如果您的线程被中断,您应该在不久的将来终止它。

        【讨论】:

          猜你喜欢
          • 2011-01-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-11
          • 2020-08-16
          • 2011-05-08
          相关资源
          最近更新 更多