“嗨,阿米戈!”
“嗨,里希!”
“我將向您介紹 Object 類的wait、notify和notifyAll方法。”
“今天我們只是熟悉一下它們,但我們稍後會回來,花更多時間在這上面。”
“好的。”
“這些方法是作為線程同步機制的一部分而發明的。”
“讓我提醒你,Java 有一個內置的機制來控制不同線程對共享資源(對象)的訪問。一個線程可以聲明一個對象處於忙碌狀態,其他線程將不得不等待,直到這個忙碌的對像被釋放。 “
“我記得。你用同步關鍵字來做到這一點。”
“對。通常,代碼看起來像這樣:”
public void print()
{
Object monitor = getMonitor();
synchronized(monitor)
{
System.out.println("text");
}
}
“還記得它是如何工作的嗎?”
“是的。如果兩個線程同時調用 print() 方法,其中一個線程將進入標記為 synchronized 的塊並鎖定監視器,這使得第二個線程將等待直到監視器被釋放。”
“對。一旦一個線程進入標記為synchronized的塊,monitor對象就被標記為busy,其他線程將被迫等待monitor對像被釋放。同一個monitor對象可以在程序的各個部分使用。 “
“對了,你為什麼選擇班長這個名字?”
“監視器就是您通常所說的存儲忙碌或空閒狀態的對象。”
“這就是等待和通知方法發揮作用的地方。”
“其實,真的就只有這兩種方法,其他的都是這些方法的改編而已。”
“現在讓我們來了解一下wait 方法是什麼以及我們為什麼需要它。 ”
“有時在程序中會出現這樣的情況,線程進入同步代碼塊並鎖定監視器,但由於缺少某些數據而無法繼續執行。例如,它需要處理的文件尚未完成下載或像那樣的東西。”
“我們可以等待文件下載。您可以使用循環檢查它。如果文件尚未下載,則休眠一秒鐘左右,然後再次檢查,直到下載完成。”
“像這樣的東西:”
while(!file.isDownloaded())
{
Thread.sleep(1000);
}
processFile(file);
“但在我們的例子中,這種等待的代價太大了。由於我們的線程鎖定了監視器,其他線程也被迫等待,即使它們可能已經擁有所需的數據。”
“發明了wait()方法來解決這個問題。這個方法導致線程釋放監視器,然後 «suspends» 線程。
“您只能在監視器繁忙時調用監視器對象的 wait 方法,即只能在同步塊內。發生這種情況時,線程會暫時停止運行,並釋放監視器,以便其他線程可以使用它。”
“通常情況下,線程會進入同步塊並調用等待,從而釋放監視器。”
“然後第二個線程將進入並暫停,然後是第三個,依此類推。”
“線程如何恢復?”
“為此,還有第二種方法:通知。”
“您只能在監視器繁忙時調用監視器對象的notify / notifyAll方法,即只能在同步塊內調用。notifyAll方法喚醒所有等待此監視器對象的線程。”
“ notify方法‘解凍’了一個隨機線程,但notifyAll方法解凍了該監視器的所有 «frozen» 線程。”
“非常有趣。謝謝你,Rishi。”
“還有對 wait() 方法的改編:”
等待() 方法 | 解釋 |
---|---|
|
線程“凍結”,但在等待作為參數傳遞給方法的毫秒數後,它會自動“解凍”。 |
|
線程“凍結”,但在等待作為參數傳遞給方法的納秒數後,它會自動“解凍”。 |
“我們也將其稱為超時等待。該方法的工作方式與普通等待一樣,但如果指定的時間已經過去並且線程尚未被喚醒,它會自行喚醒。”
GO TO FULL VERSION