Thread.interrupt() 的奇怪行为
Strange behaviour with Thread.interrupt()
我想更多地了解 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[=12=](Test.java:13)
at java.base/java.lang.Thread.run(Thread.java:834)
来自 Thread.wait
的文档(相关部分以粗体突出显示):
Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.
...
This method causes the current thread (referred to here as T) to place itself in the wait set for this object and then to relinquish any and all synchronization claims on this object.
Thread T then becomes disabled for thread scheduling purposes and lies dormant until one of the following occurs:
...
Some other thread interrupts thread T.
...
The thread T is then removed from the wait set for this object and re-enabled for thread scheduling. It competes in the usual manner with other threads for the right to synchronize on the object; once it has regained control of the object, all its synchronization claims on the object are restored to the status quo ante - that is, to the situation as of the time that the wait method was invoked. Thread T then returns from the invocation of the wait method. Thus, on return from the wait method, the synchronization state of the object and of thread T is exactly as it was when the wait method was invoked.
换句话说,当线程1被主线程中断时,它仍然需要等待线程2完成释放它的锁,然后线程1才能重新获得锁的控制权并继续。
我想更多地了解 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[=12=](Test.java:13)
at java.base/java.lang.Thread.run(Thread.java:834)
来自 Thread.wait
的文档(相关部分以粗体突出显示):
Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.
...
This method causes the current thread (referred to here as T) to place itself in the wait set for this object and then to relinquish any and all synchronization claims on this object.
Thread T then becomes disabled for thread scheduling purposes and lies dormant until one of the following occurs:
...
Some other thread interrupts thread T.
...
The thread T is then removed from the wait set for this object and re-enabled for thread scheduling. It competes in the usual manner with other threads for the right to synchronize on the object; once it has regained control of the object, all its synchronization claims on the object are restored to the status quo ante - that is, to the situation as of the time that the wait method was invoked. Thread T then returns from the invocation of the wait method. Thus, on return from the wait method, the synchronization state of the object and of thread T is exactly as it was when the wait method was invoked.
换句话说,当线程1被主线程中断时,它仍然需要等待线程2完成释放它的锁,然后线程1才能重新获得锁的控制权并继续。