當前位置:首頁 » 編程語言 » javaawait

javaawait

發布時間: 2024-04-11 08:46:42

java的等待喚醒機制必須要讓線程等待嗎

1. 線程的掛起和喚醒
掛起實際上是讓線程進入「非可執行」狀態下,在這個狀態下CPU不會分給線程時間片,進入這個狀態可以用來暫停一個線程的運行;在線程掛起後,可以通過重新喚醒線程來使之恢復運行。

掛起的原因可能是如下幾種情況:
(1)通過調用sleep()方法使線程進入休眠狀態,線程在指定時間內不會運行。
(2)通過調用join()方法使線程掛起,使自己等待另一個線程的結果,直到另一個線程執行完畢為止。
(3)通過調用wait()方法使線程掛起,直到線程得到了notify()和notifyAll()消息,線程才會進入「可執行」狀態。
(4)使用suspend掛起線程後,可以通過resume方法喚醒線程。
雖然suspend和resume可以很方便地使線程掛起和喚醒,但由於使用這兩個方法可能會造成死鎖,因此,這兩個方法被標識為deprecated(抗議)標記,這表明在以後的jdk版本中這兩個方法可能被刪除,所以盡量不要使用這兩個方法來操作線程。

調用sleep()、yield()、suspend()的時候並沒有被釋放鎖
調用wait()的時候釋放當前對象的鎖

wait()方法表示,放棄當前對資源的佔有權,一直等到有線程通知,才會運行後面的代碼。
notify()方法表示,當前的線程已經放棄對資源的佔有,通知等待的線程來獲得對資源的佔有權,但是只有一個線程能夠從wait狀態中恢復,然後繼續運行wait()後面的語句。
notifyAll()方法表示,當前的線程已經放棄對資源的佔有,通知所有的等待線程從wait()方法後的語句開始運行。

2.等待和鎖實現資源競爭
等待機制與鎖機制是密切關聯的,對於需要競爭的資源,首先用synchronized確保這段代碼只能一個線程執行,可以再設置一個標志位condition判斷該資源是否准備好,如果沒有,則該線程釋放鎖,自己進入等待狀態,直到接收到notify,程序從wait處繼續向下執行。

synchronized(obj) {
while(!condition) {
obj.wait();
}
obj.doSomething();
}

以上程序表示只有一個線程A獲得了obj鎖後,發現條件condition不滿足,無法繼續下一處理,於是線程A釋放該鎖,進入wait()。

在另一線程B中,如果B更改了某些條件,使得線程A的condition條件滿足了,就可以喚醒線程A:

synchronized(obj) {
condition = true;
obj.notify();
}

需要注意的是:
# 調用obj的wait(), notify()方法前,必須獲得obj鎖,也就是必須寫在synchronized(obj) {...} 代碼段內。
# 調用obj.wait()後,線程A就釋放了obj的鎖,否則線程B無法獲得obj鎖,也就無法在synchronized(obj) {...} 代碼段內喚醒A。
# 當obj.wait()方法返回後,線程A需要再次獲得obj鎖,才能繼續執行。
# 如果A1,A2,A3都在obj.wait(),則B調用obj.notify()只能喚醒A1,A2,A3中的一個(具體哪一個由JVM決定)。
# obj.notifyAll()則能全部喚醒A1,A2,A3,但是要繼續執行obj.wait()的下一條語句,必須獲得obj鎖,因此,A1,A2,A3隻有一個有機會獲得鎖繼續執行,例如A1,其餘的需要等待A1釋放obj鎖之後才能繼續執行。
# 當B調用obj.notify/notifyAll的時候,B正持有obj鎖,因此,A1,A2,A3雖被喚醒,但是仍無法獲得obj鎖。直到B退出synchronized塊,釋放obj鎖後,A1,A2,A3中的一個才有機會獲得鎖繼續執行。

⑵ Java中阻塞和等待的區別

定義解釋
阻塞:當一個線程試圖獲取一個內部的對象鎖(非java.util.concurrent庫中的鎖),而該鎖被其他線程持有,則該線程進入阻塞狀態。
等待:當一個線程等待另一個線程通知調度器一個條件時,該線程進入等待狀態。例如調用:Object.wait()、Thread.join()以及等待Lock或Condition。
可以通過代碼與JConsole來驗證
驗證阻塞
public static void main(String[] args) throws Exception {

Thread thread = new Thread(new Runnable() {

@Override
public void run() {
try {
// 等待主線程獲取鎖
Thread.sleep(10000);

// 請求locker對象的內部鎖
synchronized (locker) {
System.out.println("Get locker");

}
} catch (InterruptedException e) {
// TODO: handle exception
}
}
}, "Blocked Thread");
thread.start();

// 請求locker內部對象鎖
synchronized (locker) {
// 始終持有locker對象的內部鎖
while (true) {
;;
}
}

}

熱點內容
國都證券初始密碼是多少 發布:2024-05-02 07:46:39 瀏覽:109
shell腳本和linux命令行 發布:2024-05-02 07:37:54 瀏覽:968
自己的伺服器搭建微信小程序商城 發布:2024-05-02 07:36:26 瀏覽:426
php單行注釋 發布:2024-05-02 07:36:22 瀏覽:958
買車哪些配置必備 發布:2024-05-02 07:30:20 瀏覽:52
華為手機的自帶鈴聲文件夾 發布:2024-05-02 07:20:14 瀏覽:501
xp系統開機密碼怎麼設置 發布:2024-05-02 06:49:48 瀏覽:759
柱加密區公式 發布:2024-05-02 06:40:19 瀏覽:4
java位元組轉換 發布:2024-05-02 06:40:11 瀏覽:687
用c語言做的程序 發布:2024-05-02 06:26:10 瀏覽:325