(注意) t1.wait(); // 不是使t1線程等待,而是讓擁有t1這個(gè)對(duì)象的主線程等待
package test;
public class WaitTest2 {
public static void main(String[] args) {
ThreadA t1 = new ThreadA("t1");
synchronized(t1) {
try {
// 啟動(dòng)“線程t1”
System.out.println(Thread.currentThread().getName()+" start t1");
t1.start();
// 主線程等待t1通過notify()喚醒。
System.out.println("掛起主線程");
System.out.println("線程t1的狀態(tài)是:"+t1.isAlive());
t1.wait(); // 不是使t1線程等待,而是讓擁有t1這個(gè)對(duì)象的主線程等待
System.out.println("掛起主線程后面的輸出");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class ThreadA extends Thread{
public ThreadA(String name) {
super(name);
}
public void run() {
synchronized (this) {
try {
Thread.sleep(1000); // 使當(dāng)前線阻塞 1 s確保在主線程wait()之前t1沒有執(zhí)行完并退出
} catch (Exception e) {
e.printStackTrace();
}
//System.out.println(Thread.currentThread().getName()+" call notify()");
// 喚醒當(dāng)前的wait線程
//this.notify();
}
}
}
main start t1
掛起主線程
線程t1的狀態(tài)是:true
掛起主線程后面的輸出
在上面的例子中,同樣是把notify()這個(gè)方法注釋掉了,但是主線程wait()后面的代碼還是可以得到執(zhí)行,這說明了t1.wait()運(yùn)行后,不需要t1.notify()能夠喚醒!
線程正常結(jié)束后,會(huì)使以這個(gè)線程對(duì)象運(yùn)行的wait()等待,退出等待狀態(tài)!而如果在運(yùn)行wait()之前,線程已經(jīng)結(jié)束了,則這個(gè)wait就沒有程序喚醒了,例如如果上述不睡1秒的話,在主線程的t1.wait()執(zhí)行之前就運(yùn)行完畢退出那么主線程就無法被喚醒了。
實(shí)際上,Thread源碼里面的join()方法也是使用這種機(jī)制:
原碼里的join()方法,實(shí)際上就是運(yùn)行的 wait(). 需要運(yùn)行join的線程運(yùn)行join方法,實(shí)際上是在此線程上調(diào)用了需要加入的線程對(duì)象的wait()方法,加入的線程運(yùn)行完后,自然從wait退出了。
結(jié)論:
線程對(duì)象的wait()方法運(yùn)行后,可以不用其notify()方法退出,會(huì)在線程結(jié)束后,自動(dòng)退出。
線程通信.JPG
while(true) {
synchronized (r) {
if(!r.flag) {
try {
r.wait(); //雖然wait()是object的方法,任何它的子類都可以調(diào)用,但是此處還是要 用 共有資源的對(duì)象來調(diào)用
} catch (Exception e) {
}
}
System.out.println(r.name+""+r.sex+"");
r.flag=true;
r.notify();}
}