原創:轉載需注明原創地址 https://www.cnblogs.com/fanerwei222/p/11398563.html
notify() 和 wait() 主要是用來多個線程之間的協作。
它們都是Object的方法,任何對象都可以調用這兩個方法。
首先設置一個多個線程共享的對象 :
//共享對象
Object shareObject = new Object();
1.wait() :導致當前線程等待,直到另一個線程調用該對象的notify()或者notifyAll()方法;
這里用代碼解釋一下:
class ThreadOne extends Thread{ @Override public void run() { synchronized (shareObject){ for (int i = 0; i < 10 ; i++){ System.out.println("A線程--->"+i); shareObject.notify(); if (first){ first = false; try { shareObject.wait(); } catch (Exception e){ System.out.println(e); } } } } } }
這里的 shareObject.wait(); 會導致ThreadOne線程進入shareObject對象的等待隊列(這個等待隊列可能會有多個線程,這些線程都停止繼續執行,進入等待狀態),直到其他線程調用shareObject的notify()或者notifyAll()方法,ThreadOne線程就可能會被喚醒,因為該喚醒是從等待隊列中隨機抽取一個線程進行喚醒,不公平喚醒。
2.notify() :喚醒正在等待對象監視器的單個線程。這個在上面已經作了解釋,下面用代碼說明一下。
class ThreadTwo extends Thread{ @Override public void run() { synchronized (shareObject){ for (int i = 0; i < 10; i++){ System.out.println("B線程--->"+i); shareObject.notify(); if (!first){ first = true; try { shareObject.wait(); }catch (Exception e){ System.out.println(e); } } } } } }
這里的 shareObject.notify();會從shareObject對象的等待隊列中隨機喚醒一個線程,但是目前的shareObject對象的等待隊列中只有ThreadOne一個線程,所以它就被喚醒了。
過程如下圖:
最后:wait和sleep區別
1️⃣ wait和sleep方法都可以讓線程等待;
2️⃣ wait()方法可以被喚醒,sleep不能被喚醒。
3️⃣ wait()既會釋放cpu,也會釋放共享資源的鎖,sleep()不會釋放任何資源。
4️⃣ wait和sleep方法都可以使線程進人阻塞狀態。
5️⃣ wait和sleep方法均是可中斷方法,被中斷后都會收到中斷異常。
6️⃣ wait是Object的方法,而sleep是Thread特有的方法。
7️⃣ wait方法的執行必須在同步方法中進行,而sleep則不需要。
8️⃣ 線程在同步方法中執行sleep方法時,並不會釋放monitor的鎖,而wait方法則會釋放monitor的鎖。
9️⃣ sleep方法短暫休眠之后會主動退出阻塞,而wait方法(沒有指定wait時間)則需要被其他線程中斷后才能退出阻塞。
🔟 sleep:是Thread的靜態方法,會使當前線程釋放cpu,但不會釋放鎖資源,可以理解為只和cpu有關,不涉及鎖資源。涉及鎖資源的,是wait,join方法。
🔟1️⃣ yield:也是Thread的靜態方法,和sleep方法類似,會使當前線程釋放cpu,但不會釋放鎖資源。和sleep不同的是,sleep必須設置時間,但是yield不能設置時間,時間值是隨機的
🔟2️⃣ join: 等待join方法執行線程先執行完畢, main方法再繼續執行; 例如 main方法中有一個線程thread執行了thread.join() ; 那么當main方法執行到了thread.join()語句時,必須等待thread線程執行完畢,才能繼續執行;thread必須執行了start方法才會這樣,如果沒有執行start方法main方法會直接執行下去.
結束🔚