導航:首頁 > 編程語言 > java線程等待喚醒

java線程等待喚醒

發布時間:2022-05-31 17:01:10

A. java 中 當一線程處於等待狀態時,用什麼方法可以將其喚醒

notify() 或 notifyAll()方法

B. java線程中怎麼喚醒被wait的線程

notify()方法
無法指定。選擇是任意性的。
喚醒在此對象監視器上等待的單個線程。如果有多個線程都在此對象上等待,則會選擇喚醒其中一個線程。

C. java 線程 喚醒問題

首先,從你程序的本意來看, 你是想用線程實現一個生產者-- 消費者模式, 用在饅頭的場景, 如下:

1、 肯定需要一個籃子, 負責裝饅頭,並且這個籃子有容量,假設容量為C;
2、 有兩個人,第一個是爹(生產者), 第二個是娃(消費者), 爹負責向籃子中放入饅頭, 娃負責從籃子中取出饅頭喂狗;
3、 但是籃子的容量是有限的, 當籃子被裝滿時, 爹就等待娃從籃子中取出饅頭,籃子騰出空間之後,爹繼續裝饅頭; 當籃子的饅頭都被取走後, 娃就等待, 當籃子中又被放入饅頭時,才繼續取饅頭。

附上代碼:

籃子:

public class Bucket {
private int count = 0; // 籃子能夠容納的饅頭數
private int total = 0; // 放饅頭的總數

public synchronized void put(){
if(count == 5){
try {
System.out.println("俺是他爹,籃子滿了,俺在等俺家娃拿饅頭喂狗");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

count += 1;
total++;
System.out.println("俺是他爹,俺放了一個饅頭,現有籃子里有 [" + count + "] 個饅頭");
notify();
}

public synchronized boolean get(){
if(count == 0){
try {
wait();
System.out.println("俺是他娃,籃子空了,俺在等俺爹放饅頭到籃子里");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count -= 1;
System.out.println("俺拿了一個饅頭喂俺家大花狗, 籃子里還有 [" + count + "] 個饅頭");
notify();

if(total == 100 && count == 0){
return false;
}else{
return true;
}
}

爹:

public class Proct implements Runnable{

private Bucket bucket;
Proct(Bucket bucket){
this.bucket = bucket;
}

@Override
public void run() {
for(int i=0; i<100; i++){
bucket.put();
}
System.out.println("俺把饅頭都放完了");
}
}

娃:

public class Consumer implements Runnable{

private Bucket bucket;
public Consumer(Bucket bucket){
this.bucket = bucket;
}

@Override
public void run() {
while(true){
if(!bucket.get()){
break;
}
}
System.out.println("俺家大花狗吃完饅頭了");
}

}

啟動類:

public class Test {

public static void main(String[] args) {

Bucket bucket = new Bucket();
new Thread(new Consumer(bucket)).start();
new Thread(new Proct(bucket)).start();
}
}

最後附上你的問題, notify 由誰來喚醒:

注意 wait() 和 notify() 是Object類上的方法,
notify() 的意思是: 從加鎖的對象的監視器(監視器就是鎖)的等待隊列中, 任意取出一個等待線程, 讓該線程處於runnable狀態;
wait()的意思是: 把鎖住對象的當前線程, 放入到監視器的等待隊列中。

所以,notify()的意思就是要喚醒等待隊列中的一個等待線程,當程序發起這么一個事件後, 是由虛擬機的線程調度器完成線程狀態之間的轉換的。

D. java 多線程子線程喚醒主線程問題

設一個三個線程的共享對象o
a.start();
b.start();//啟動子線程
主線程中
o.wait(10*1000);//主線程中等10秒
同時A、B中各有一個執行完的通知
a或b的run(){
.....
o.
notify();
}
基本的線程操作...

E. java 線程 喚醒等待問題

synchronized(this) { notify(); } 所以喚醒的是自己吧?

正確的做法是 thread2 在某個鎖上 wait,另外,在絕大多數情況下都把 notify 換成 notifyAll。因為 notify 一次只喚醒一個,多數情況下我們是根據條件來喚醒的。

Object lock = new Object();
// 線程2
lock.wait();

// 線程1
lock.notifyAll();

F. 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中的一個才有機會獲得鎖繼續執行。

G. Java線程喚醒與阻塞常用方法有哪些

如果線程是因為調用了wait()、sleep()或者join()方法而導致的阻塞,可以中斷線程,並且通過拋出InterruptedException來喚醒它;如果線程遇到了IO阻塞,無能為力,因為IO是操作系統實現的,Java代碼並沒有辦法直接接觸到操作系統。以下是詳細的喚醒方法:

1. sleep() 方法

sleep(毫秒),指定以毫秒為單位的時間,使線程在該時間內進入線程阻塞狀態,期間得不到cpu的時間片,等到時間過去了,線程重新進入可執行狀態。(暫停線程,不會釋放鎖)

2.suspend() 和 resume() 方法

掛起和喚醒線程,suspend e()使線程進入阻塞狀態,只有對應的resume e()被調用的時候,線程才會進入可執行狀態。(不建議用,容易發生死鎖)

3. yield() 方法

會使的線程放棄當前分得的cpu時間片,但此時線程任然處於可執行狀態,隨時可以再次分得cpu時間片。yield()方法只能使同優先順序的線程有執行的機會。調用 yield()的效果等價於調度程序認為該線程已執行了足夠的時間從而轉到另一個線程。(暫停當前正在執行的線程,並執行其他線程,且讓出的時間不可知)

4.wait() 和 notify() 方法

兩個方法搭配使用,wait()使線程進入阻塞狀態,調用notify()時,線程進入可執行狀態。wait()內可加或不加參數,加參數時是以毫秒為單位,當到了指定時間或調用notify()方法時,進入可執行狀態。(屬於Object類,而不屬於Thread類,wait()會先釋放鎖住的對象,然後再執行等待的動作。由於wait()所等待的對象必須先鎖住,因此,它只能用在同步化程序段或者同步化方法內,否則,會拋出異常IllegalMonitorStateException.)

5.join()方法

也叫線程加入。是當前線程A調用另一個線程B的join()方法,當前線程轉A入阻塞狀態,直到線程B運行結束,線程A才由阻塞狀態轉為可執行狀態。

以上是Java線程喚醒和阻塞的五種常用方法,不同的方法有不同的特點,其中wait() 和 notify()是其中功能最強大、使用最靈活的方法,但這也導致了它們效率較低、較容易出錯的特性,因此,在實際應用中應靈活運用各種方法,以達到期望的目的與效果!

H. java 中當一線程處於等待狀態時,用什麼方法可以將其喚醒

如果線程在睡覺,調用這個線程對象的interrupt方法
如果這個線程在等待一個對象的鎖,那麼調用那個對象的notifyAll方法

閱讀全文

與java線程等待喚醒相關的資料

熱點內容
方舟如何刪除伺服器數據 瀏覽:600
用閱讀app怎麼看18 瀏覽:689
gn文件編譯 瀏覽:783
酷閃加密系統 瀏覽:820
區塊鏈數據加密 瀏覽:389
3d命令集 瀏覽:289
單片機的智能產品工廠里有 瀏覽:300
事業單位程序員有必要去嗎 瀏覽:583
人工智慧訓練小鳥python 瀏覽:132
怎樣把兩個pdf合並成一個 瀏覽:681
什麼app帶仿製圖章 瀏覽:420
單片機CJNE什麼意思 瀏覽:569
廊坊伺服器是什麼 瀏覽:763
客戶解壓要打欠條還是收據 瀏覽:774
通過app組件啟動有什麼壞處 瀏覽:775
不屬於國產密碼演算法 瀏覽:861
單片機LED顯示字型檔 瀏覽:353
日本文件夾品牌十大名牌 瀏覽:397
靜脈壓縮襪和打底褲的區別 瀏覽:345
勁舞伺服器中斷是什麼原因 瀏覽:630