62,614
社区成员
发帖
与我相关
我的任务
分享
package com.test.notify;
public class WaitNotifyTest {
static Object lock = 1;
public static void main(String[] args) throws InterruptedException{
new PingPong("t1", 0).start();
new PingPong("t2", 1).start();
}
}
class PingPong extends Thread{
int i;
String name;
PingPong(String name, int i){
this.name = name;
this.i = i;
}
@Override
public void run(){
for (int i = this.i; i<20; i+=2){
try {
synchronized (WaitNotifyTest.class){
System.out.println(this.name + ": notify");
WaitNotifyTest.class.notify();
System.out.println(this.name + ": " + i);
//while (i!=20){//移除注释运行会出错
System.out.println(this.name + ": wait");
WaitNotifyTest.class.wait();
//}
}
}
catch (InterruptedException e){
System.err.println(this.name + ": " + e.getMessage());
}
}
}
}
/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/lib/tools.jar:/Users/gucci/Documents/java_course/Homework2/target/classes:/Users/gucci/.m2/repository/org/apache/poi/poi/3.14/poi-3.14.jar:/Users/gucci/.m2/repository/commons-codec/commons-codec/1.10/commons-codec-1.10.jar:/Users/gucci/.m2/repository/org/apache/pdfbox/pdfbox/2.0.13/pdfbox-2.0.13.jar:/Users/gucci/.m2/repository/org/apache/pdfbox/fontbox/2.0.13/fontbox-2.0.13.jar:/Users/gucci/.m2/repository/commons-logging/commons-logging/1.2/commons-logging-1.2.jar com.test.notify.WaitNotifyTest
t1: notify
t1: 0
t1: wait
t2: notify
t2: 1
t2: wait
t1: notify
t1: 2
t1: wait
t2: notify
t2: 3
t2: wait
t1: notify
t1: 4
t1: wait
t2: notify
t2: 5
t2: wait
t1: notify
t1: 6
t1: wait
t2: notify
t2: 7
t2: wait
t1: notify
t1: 8
t1: wait
t2: notify
t2: 9
t2: wait
t1: notify
t1: 10
t1: wait
t2: notify
t2: 11
t2: wait
t1: notify
t1: 12
t1: wait
t2: notify
t2: 13
t2: wait
t1: notify
t1: 14
t1: wait
t2: notify
t2: 15
t2: wait
t1: notify
t1: 16
t1: wait
t2: notify
t2: 17
t2: wait
t1: notify
t1: 18
t1: wait
t2: notify
t2: 19
t2: wait
t1: notify
t1: 0
t1: wait
t2: notify
t2: 1
t2: wait
t1: wait
t1: notify
t1: 0
t1: wait
t2: notify
t2: 1
t2: wait
t1: wait
根据上面的输出来分析,首先是t1执行第一次,获取到锁,唤醒等待锁的线程t2,打印t1: notify,t1: 0,紧接着进入了while循环的判断,此时i不等于20,执行while循环方法体,打印t1: wait,释放锁等待唤醒,注意此时没有跳出while循环,只是t1线程进入等待锁的状态,下次获取到锁后继续执行while循环.
t2获取到锁,唤醒等待锁的t1,打印t2: notify,t2: 1,同样的进入了while循环判断,此时i为1不等于20,执行while循环方法体,打印t2: wait,释放锁等待唤醒,下次获取到锁后继续执行while循环.
t1获取到锁,继续执行while循环,此时i还是0,不等于20,打印t1: wait,释放锁等待唤醒,注意此时两个线程都进入了等待唤醒的状态,如下图
估计你的盲点是执行完wait()方法后线程再次获取到锁时,应该如何执行.执行wait()方法时会保存当前上下文,也就是当前时间点 CPU 寄存器和程序计数器的内容,下次获取到锁后,会从保存的上下文加载当时的状态,继续执行wait()方法后续的代码,这其实就是上下文切换.为了验证这个问题,可以在while循环的方法体中在wait()方法后加一句System.out.println("这是恢复后执行的代码"+this.name);整体来看就是
package com.test.notify;
public class WaitNotifyTest {
static Object lock = 1;
public static void main(String[] args) throws InterruptedException{
new PingPong("t1", 0).start();
new PingPong("t2", 1).start();
}
}
class PingPong extends Thread{
int i;
String name;
PingPong(String name, int i){
this.name = name;
this.i = i;
}
@Override
public void run(){
for (int i = this.i; i<20; i+=2){
try {
synchronized (WaitNotifyTest.class){
System.out.println(this.name + ": notify");
WaitNotifyTest.class.notify();
System.out.println(this.name + ": " + i);
while (i!=20){
System.out.println(this.name + ": wait");
WaitNotifyTest.class.wait();
//这是新添加的代码
System.out.println("这是恢复后执行的代码"+this.name);
}
}
}
catch (InterruptedException e){
System.err.println(this.name + ": " + e.getMessage());
}
}
}
}
控制台输出结果:
t1: notify
t1: 0
t1: wait
t2: notify
t2: 1
t2: wait
这是恢复后执行的代码t1
t1: wait
从打印结果来看"这是恢复后执行的代码t1"比后一次"t1: wait"先打印,也就证明了wait()后的线程再次获取到锁时,继续执行的是wait()方法后的代码.
while (i!=20){//移除注释运行会出错
System.out.println(this.name + ": wait");
WaitNotifyTest.class.wait();
}
循环代码存在时, t1 执行等待后,释放 对象锁,t2 执行,t2 notify 唤醒t1,t2 执行 wait后 释放对象锁,t1 被唤醒继续执行,又进入 while循环,执行wait, 现在 t1,t2 全部处于等待,死锁了;