同事贴出来的代码
问题1 : 我已经让这个线程wait()了,没有地方唤醒它,怎么也执行了啊
public class MyThread extends Thread
{
/**
* @param args
*/
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
MyThread myThread = new MyThread();
myThread.setName("myThread");
try {
myThread.start();
myThread.wait();
for (int i = 0; i < 10; i++) {
int sleepTime = (int) (Math.random()*1000);
Thread.sleep(sleepTime);
System.out.println("main="+Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
*
*/
public void run() {
try {
for (int i = 0; i < 10; i++) {
int sleepTime = (int) (Math.random()*1000);
Thread.sleep(sleepTime);
System.out.println("run="+Thread.currentThread().getName());
}
} catch (Exception e){
e.printStackTrace();
}
}
}
这个问题所在就是wait要配合synchronized使用,否则会出现上面的异常,导致wait方法调用失败,至于为什么要与synchronized一起使用主要是为了避免 lost wake-up问题 ,感兴趣可以了解这篇博客 https://blog.youkuaiyun.com/weixin_30828379/article/details/99188103
所以要想正确执行可以稍微改一下
public class MyThread extends Thread
{
/**
* @param args
*/
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
MyThread myThread = new MyThread();
synchronized (myThread) {
myThread.setName("myThread");
try {
myThread.start();
myThread.wait();
for (int i = 0; i < 10; i++) {
System.out.println("main="+Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void run() {
try {
for (int i = 0; i < 10; i++) {
System.out.println("run="+Thread.currentThread().getName());
}
} catch (Exception e){
e.printStackTrace();
}
}
}
执行结果如下
问题2:这时候同事的问题又来了,main线程不是被wait了吗,为什么最后还是输出了最后的for循环内的输出语句?
这个问题一开始我也有点纳闷,但是我的理解是main方法一开始被wait住了,但是wait它的是一个线程(也就是myThread),在myThread做完了run方法的事情后,这个myThread线程的生命周期结束了,myThread线程终结消亡了,所以监听对象消亡我认为就相当于notifyAll了,这个时候main线程就没有被阻塞下去了,后面的语句得到了执行。(个人理解)
问题3:对 wait方法的理解存在误区,以为wait方法是阻塞了上面的myThread这一线程。
实际上wait方法是阻塞当前线程,在这个例子中它阻塞的是main线程而并非是myThread这个线程