线程中断。有人可以向我解释输出以更好地理解中断吗?

Thread Interrupts. Can someone explain me the output to understand interrupts better?

我能够理解线程和中断。我试图映射从 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

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

中断一个线程意味着向它发出停止当前正在做的事情的信号。

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

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

Once a thread is interrupted, it is basically taken out of operation as per my understanding.

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

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

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

这是您在线程中断时选择执行的操作:

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

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

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

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

  • 主线程创建并启动了 3 个名为:Fred、Lucy、Ricky 的线程。我们只考虑名为 Fred 的线程,它被分配给变量 one(有更好的方法可以做到这一点,例如 CountdownLatch)。
  • Fred,在被安排到 运行 之后,您的代码会立即让他入睡。方法 Thread.sleep 是一个精心设计的 阻塞调用 。这意味着它可以通过发送中断来中断。这正是主线程试图做的:请求中断 activity 线程 one 正在做或不做的事情(因为在这种情况下它只是在睡觉)。 main 线程通过简单地调用 one 上的 interrupt() 方法来做到这一点。请注意,这仅被中断的线程视为 'friendly request'。
  • 在您看到输出 'Exception occurred' 的情况下,(睡眠中的)中断线程确认了中断,并且像记录的那样,抛出 InterruptedException。此异常被 one 捕获,消息 'Exception occurred' 打印在标准输出上。因此,主线程 已成功中断 one 正在做的事情
  • 其他线程不间断地执行任务(这就是您看到其他打印语句的原因)。