【问题标题】:Strange behaviour with Thread.interrupt()Thread.interrupt() 的奇怪行为
【发布时间】:2022-01-25 08:52:35
【问题描述】:

我试图了解更多关于 Thread.interrupt() 的信息,因此我编写了以下代码。

public class Test {

    private Object object = new Object();

    Runnable thread1 = () -> {
        synchronized (object) {
            System.out.println(System.currentTimeMillis() + " - Thread1 inside synchronized block");
            try {
                object.wait();
                System.out.println(System.currentTimeMillis() + " - Thread1 after wait()");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(System.currentTimeMillis() + " - Thread1 ending");
        }
    };

    Runnable thread2 = () -> {
        synchronized (object) {
            System.out.println(System.currentTimeMillis() + " - Thread2 inside synchronized block");
            try {
                Thread.sleep(2000);
                System.out.println(System.currentTimeMillis() + " - Thread2 after sleep");
                object.notify();
                System.out.println(System.currentTimeMillis() + " - Thread2 after notify()");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(System.currentTimeMillis() + " - Thread2 ending");
        }
    };

    public void run() {
        Thread t1 = new Thread(thread1);
        Thread t2 = new Thread(thread2);
        t1.start();
        t2.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t1.interrupt();
    }

    public static void main(String[] args) {
        new Test().run();
    }

}

我无法理解结果。首先,为什么输出的第三行没有显示异常堆栈跟踪?第一个线程在第二个线程仍在休眠时被中断,因此异常应该在第二个线程醒来之前发生。其次,为什么在堆栈跟踪之前出现“线程 1 结束”?

1643099950931 - Thread1 inside synchronized block
1643099950947 - Thread2 inside synchronized block
1643099952947 - Thread2 after sleep
1643099952947 - Thread2 after notify()
1643099952947 - Thread2 ending
1643099952947 - Thread1 ending
java.lang.InterruptedException
    at java.base/java.lang.Object.wait(Native Method)
    at java.base/java.lang.Object.wait(Object.java:328)
    at com.ocbc.ms.Test.lambda$new$0(Test.java:13)
    at java.base/java.lang.Thread.run(Thread.java:834)

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    来自Thread.wait的文档(相关部分以粗体突出显示):

    使当前线程等待直到它被唤醒,通常是通过通知中断,或者直到经过一定的实时时间。

    ...

    此方法使当前线程(此处称为 T)将自己置于此对象的等待集中,然后放弃对该对象的所有同步声明。

    线程 T 然后出于线程调度目的而被禁用并处于休眠状态,直到发生以下情况之一:

    • ...

    • 其他一些线程中断线程T。

    • ...

    线程 T 然后从该对象的等待集中移除并重新启用线程调度。 它以通常的方式与其他线程竞争对象同步的权利;一旦它重新获得对对象的控制权,它对对象的所有同步声明都将恢复到之前的状态——即就是调用wait方法时的情况。线程 T 然后从调用等待方法返回。因此,从等待方法返回时,对象和线程 T 的同步状态与调用等待方法时完全相同。

    也就是说,当线程 1 被主线程中断时,它仍然要等待线程 2 完成释放它的锁,然后线程 1 才会重新获得对锁的控制并继续。

    【讨论】:

    • 我想我理解文档。但我仍然不明白为什么堆栈跟踪是在“线程 1 结束”之后出现的。
    • @user3573403 这实际上是与herehere 讨论的Java 中的std 输出和错误流相关的不同问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-08
    • 2015-07-20
    • 2010-10-03
    • 2021-07-12
    • 2013-10-04
    • 2019-01-23
    相关资源
    最近更新 更多