導航:首頁 > 編程語言 > java多線程ifwait

java多線程ifwait

發布時間:2022-11-26 04:42:56

java多線程有幾種狀態

新建(new)

新建一個線程的對象。

可運行(runable)

線程對象創建後,其他線程調用該線程的start方法。或者該線程位於可運行線程池中等待被線程調用,已獲取cpu的使用權。

運行(running)

可運行的線程獲取了cpu的使用權,執行程序代碼/

阻塞(block)

由於某些原因該線程放棄了cpu的使用權。停止執行。除非線程進入可運行的狀態,才會有機會獲取cpu的使用權。

1. 等待阻塞:運行中的線程執行wait方法,這時候該線程會被放入等待隊列。

2. 同步阻塞:運行中的線程獲取同步鎖,如果該同步鎖被別的線程佔用,這個線程會成被放入鎖池,等待其他線程釋放同步鎖。

3. 其他阻塞:運行的線程執行sleep或者join方法這個線程會成為阻塞狀態。當sleep超時,join等待線程終止,該線程會進入可運行狀態。

死亡(dead)

線程run mian 執行完畢後,或者因為某些異常產生退出了 run 方法,該線程的生命周期結束。

② java線程,wait()方法怎麼把自己給停掉了

Thread.currentThread().wait() //引用當前的線程

③ JAVA多線程suspend,resume和wait,notify的區別

suspend,使線程進入停滯狀態,除非收到resume消息,否則該線程不會變回可執行狀態。
wait():使一個線程處於等待狀態,並且釋放所持有的對象的lock;
sleep():使一個正在運行的線程處於睡眠狀態,是一個靜態方法,調用此方
法要捕捉InterruptedException異常;
notify():喚醒一個處於等待狀態的線程,注意的是在調用此方法的時候,
並不能確切的喚醒某一個等待狀態的線程,而是由JVM確定喚醒哪個線程,而且
不是按優先順序;
notityAll():喚醒所有處入等待狀態的線程,注意並不是給所有喚醒線程一
個對象的鎖,而是讓它們競爭。

④ java中if (){ wait();}else{},假如判斷完if後wait了,notify後如何運行

1、如果一個線程調用了某個對象的wait方法,那麼該線程進入到該對象的等待池中(並且已經將鎖釋放), 如果未來的某一時刻,另外一個線程調用了相同對象的notify方法或者notifyAll方法, 那麼該等待池中的線程就會被喚起,然後進入到對象的鎖池裡面去獲得該對象的鎖, 如果獲得鎖成功後,那麼該線程就會沿著wait方法之後的路徑繼續執行。注意是沿著wait方法之後 2.如果沒有直接性的調用同類里的其他介面,或者返回,結束等java關鍵字,代碼還是得往下執行的。

⑤ JAVA線程wait()方法問題

應該使用wait(),wait 方法的解釋是
Causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.

舉個例子:
比如你有一個Depository 類的對象 d ,然後線程A要訪問d的addLast()方法,
因為這個addLast()方法時synchronized 所以線程A進入的時候就給這個對象d 加上鎖,其它線程不允許訪問,當執行到wait()時,線程A就會先打開對象A的鎖,並在對象d 外面排隊等待。

對於IllegalMonitorStateException,我的理解是:
一個對象的wait()方法只能在此對象的同步方法中被調用,意思是,這個對象在wait前是被加了鎖的。

你將addLast方法的synchronized 去掉運行也會拋出這樣的異常。

所以說你用wait()就可以了。
Thread.currentThread().wait();這句話調用的是當前線程對象的wait()方法,
當前線程對象沒有被加鎖。所以出錯。

個人理解,僅供參考,希望能幫到你

⑥ 如何在 Java 中正確使用 wait,notify 和 notifyAll

我們先來了解一下為什麼要使用wait,notify


首先看一下以下代碼:

synchronized(a){
...//1
synchronized(b){
}
}
synchronized(b){
...//2
synchronized(a){
}
}

假設現在有兩個線程, t1 線程運行到了//1 的位置,而 t2 線程運行到了//2 的位置,接

下來會發生什麼情況呢?

此時, a 對象的鎖標記被 t1 線程獲得,而 b 對象的鎖標記被 t2 線程獲得。對於 t1 線程

而言,為了進入對 b 加鎖的同步代碼塊, t1 線程必須獲得 b 對象的鎖標記。由於 b 對象的鎖標記被 t2 線程獲得, t1 線程無法獲得這個對象的鎖標記,因此它會進入 b 對象的鎖池,等待 b 對象鎖標記的釋放。而對於 t2 線程而言,由於要進入對 a 加鎖的同步代碼塊,由於 a 對象的鎖標記在 t1 線程手中,因此 t2 線程會進入 a 對象的鎖池。

此時, t1 線程在等待 b 對象鎖標記的釋放,而 t2 線程在等待 a 對象鎖標記的釋放。由

於兩邊都無法獲得所需的鎖標記,因此兩個線程都無法運行。這就是「死鎖」問題。


在 Java 中,採用了 wait 和 notify 這兩個方法,來解決死鎖機制。

首先,在 Java 中,每一個對象都有兩個方法: wait 和 notify 方法。這兩個方法是定義

在 Object 類中的方法。對某個對象調用 wait()方法,表明讓線程暫時釋放該對象的鎖標記。

例如,上面的代碼就可以改成:

synchronized(a){
...//1
a.wait();
synchronized(b){
}
}
synchronized(b){
...//2
synchronized(a){
...
a.notify();
}
}

這樣的代碼改完之後,在//1 後面, t1 線程就會調用 a 對象的 wait 方法。此時, t1 線程

會暫時釋放自己擁有的 a 對象的鎖標記,而進入另外一個狀態:等待狀態。

要注意的是,如果要調用一個對象的 wait 方法,前提是線程已經獲得這個對象的鎖標

記。如果在沒有獲得對象鎖標記的情況下調用 wait 方法,則會產生異常。

由於 a 對象的鎖標記被釋放,因此, t2 對象可以獲得 a 對象的鎖標記,從而進入對 a

加鎖的同步代碼塊。在同步代碼塊的最後,調用 a.notify()方法。這個方法與 wait 方法相對應,是讓一個線程從等待狀態被喚醒。

那麼 t2 線程喚醒 t1 線程之後, t1 線程處於什麼狀態呢?由於 t1 線程喚醒之後還要在

對 a 加鎖的同步代碼塊中運行,而 t2 線程調用了 notify()方法之後,並沒有立刻退出對 a 鎖的同步代碼塊,因此此時 t1 線程並不能馬上獲得 a 對象的鎖標記。因此,此時, t1 線程會在 a 對象的鎖池中進行等待,以期待獲得 a 對象的鎖標記。也就是說,一個線程如果之前調用了 wait 方法,則必須要被另一個線程調用 notify()方法喚醒。喚醒之後,會進入鎖池狀態。線程狀態轉換圖如下:

classConsumerextendsThread{
privateMyStackms;
publicConsumer(MyStackms){
this.ms=ms;
}
publicvoidrun(){
while(true){
//為了保證push和pop操作的完整性
//必須加synchronized
synchronized(ms){
//如果棧空間已滿,則wait()釋放ms的鎖標記
while(ms.isEmpty()){
try{
ms.wait();
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
charch=ms.pop();
System.out.println("Pop"+ch);
ms.notifyAll();
}
//push之後隨機休眠一段時間
try{
sleep((int)Math.abs(Math.random()*100));
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}
//生產者
classProcerextendsThread{
privateMyStackms;
publicProcer(MyStackms){
this.ms=ms;
}
publicvoidrun(){
while(true){
//為了保證push和pop操作的完整性
//必須加synchronized
synchronized(ms){
//如果棧空間已滿,則wait()釋放ms的鎖標記
while(ms.isFull()){
try{
ms.wait();
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
ms.push('A');
System.out.println("pushA");
ms.notifyAll();
}
//push之後隨機休眠一段時間
try{
sleep((int)Math.abs(Math.random()*200));
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}
//主方法中,啟用生產者與消費者兩個線程
publicclassTestWaitNotify{
publicstaticvoidmain(String[]args){
MyStackms=newMyStack();
Threadt1=newProcer(ms);
Threadt2=newConsumer(ms);
t1.start();
t2.start();
}
}

部分代碼純手打,望採納~

⑦ 如何在 Java 中正確使用 wait,notify 和 notifyAll

wait, notify 和 notifyAll,這些在多線程中被經常用到的保留關鍵字,在實際開發的時候很多時候卻並沒有被大家重視。本文對這些關鍵字的使用進行了描述。
在 Java 中可以用 wait、notify 和 notifyAll
來實現線程間的通信。。舉個例子,如果你的Java程序中有兩個線程——即生產者和消費者,那麼生產者可以通知消費者,讓消費者開始消耗數據,因為隊列緩
沖區中有內容待消費(不為空)。相應的,消費者可以通知生產者可以開始生成更多的數據,因為當它消耗掉某些數據後緩沖區不再為滿。
我們可以利用wait()來讓一個線程在某些條件下暫停運行。例如,在生產者消費者模型中,生產者線程在緩沖區為滿的時候,消費者在緩沖區為空的時
候,都應該暫停運行。如果某些線程在等待某些條件觸發,那當那些條件為真時,你可以用 notify 和 notifyAll
來通知那些等待中的線程重新開始運行。不同之處在於,notify 僅僅通知一個線程,並且我們不知道哪個線程會收到通知,然而 notifyAll
會通知所有等待中的線程。換言之,如果只有一個線程在等待一個信號燈,notify和notifyAll都會通知到這個線程。但如果多個線程在等待這個信
號燈,那麼notify只會通知到其中一個,而其它線程並不會收到任何通知,而notifyAll會喚醒所有等待中的線程。
在這篇文章中你將會學到如何使用 wait、notify 和 notifyAll 來實現線程間的通信,從而解決生產者消費者問題。如果你想要更深入地學習Java中的多線程同步問題,我強烈推薦閱讀Brian Goetz所著的《Java Concurrency in Practice | Java 並發實踐》,不讀這本書你的 Java 多線程征程就不完整哦!這是我最向Java開發者推薦的書之一。
如何使用Wait
盡管關於wait和notify的概念很基礎,它們也都是Object類的函數,但用它們來寫代碼卻並不簡單。如果你在面試中讓應聘者來手寫代碼,
用wait和notify解決生產者消費者問題,我幾乎可以肯定他們中的大多數都會無所適從或者犯下一些錯誤,例如在錯誤的地方使用
synchronized 關鍵詞,沒有對正確的對象使用wait,或者沒有遵循規范的代碼方法。說實話,這個問題對於不常使用它們的程序員來說確實令人感覺比較頭疼。
第一個問題就是,我們怎麼在代碼里使用wait()呢?因為wait()並不是Thread類下的函數,我們並不能使用
Thread.call()。事實上很多Java程序員都喜歡這么寫,因為它們習慣了使用Thread.sleep(),所以他們會試圖使用wait()

來達成相同的目的,但很快他們就會發現這並不能順利解決問題。正確的方法是對在多線程間共享的那個Object來使用wait。在生產者消費者問題中,這
個共享的Object就是那個緩沖區隊列。
第二個問題是,既然我們應該在synchronized的函數或是對象里調用wait,那哪個對象應該被synchronized呢?答案是,那個

你希望上鎖的對象就應該被synchronized,即那個在多個線程間被共享的對象。在生產者消費者問題中,應該被synchronized的就是那個
緩沖區隊列。(我覺得這里是英文原文有問題……本來那個句末就不應該是問號不然不太通……)
永遠在循環(loop)里調用 wait 和 notify,不是在 If 語句
現在你知道wait應該永遠在被synchronized的背景下和那個被多線程共享的對象上調用,下一個一定要記住的問題就是,你應該永遠在
while循環,而不是if語句中調用wait。因為線程是在某些條件下等待的——在我們的例子里,即「如果緩沖區隊列是滿的話,那麼生產者線程應該等
待」,你可能直覺就會寫一個if語句。但if語句存在一些微妙的小問題,導致即使條件沒被滿足,你的線程你也有可能被錯誤地喚醒。所以如果你不在線程被喚

醒後再次使用while循環檢查喚醒條件是否被滿足,你的程序就有可能會出錯——例如在緩沖區為滿的時候生產者繼續生成數據,或者緩沖區為空的時候消費者
開始小號數據。所以記住,永遠在while循環而不是if語句中使用wait!我會推薦閱讀《Effective Java》,這是關於如何正確使用wait和notify的最好的參考資料。
基於以上認知,下面這個是使用wait和notify函數的規范代碼模板:
// The standard idiom for calling the wait method in Java synchronized (sharedObject) { while (condition) { sharedObject.wait(); // (Releases lock, and reacquires on wakeup) } // do action based upon condition e.g. take or put into queue }
就像我之前說的一樣,在while循環里使用wait的目的,是在線程被喚醒的前後都持續檢查條件是否被滿足。如果條件並未改變,wait被調用之前notify的喚醒通知就來了,那麼這個線程並不能保證被喚醒,有可能會導致死鎖問題。
Java wait(), notify(), notifyAll() 範例
下面我們提供一個使用wait和notify的范常式序。在這個程序里,我們使用了上文所述的一些代碼規范。我們有兩個線程,分別名為
PRODUCER(生產者)和CONSUMER(消費者),他們分別繼承了了Procer和Consumer類,而Procer和
Consumer都繼承了Thread類。Procer和Consumer想要實現的代碼邏輯都在run()函數內。Main線程開始了生產者和消費
者線程,並聲明了一個LinkedList作為緩沖區隊列(在Java中,LinkedList實現了隊列的介面)。生產者在無限循環中持續往
LinkedList里插入隨機整數直到LinkedList滿。我們在while(queue.size ==
maxSize)循環語句中檢查這個條件。請注意到我們在做這個檢查條件之前已經在隊列對象上使用了synchronized關鍵詞,因而其它線程不能在
我們檢查條件時改變這個隊列。如果隊列滿了,那麼PRODUCER線程會在CONSUMER線程消耗掉隊列里的任意一個整數,並用notify來通知
PRODUCER線程之前持續等待。在我們的例子中,wait和notify都是使用在同一個共享對象上的。

⑧ java 線程中wait和notify的問題

這個程序挺經典的.

我不知道你對wait這是不是很熟,我按我的說,有問題再溝通:

首先看
main函數,兩句話,Procer對象和Consumer對象都引用了同一個p.
Procer類的run
前面有
synchronized(p)
說明該線程用到 synchronized 里的對象變數時,別的線程只能等待.
再看
if(p.bFull) {
try{p.wait();} catch (Exception e) {}
}
也就是說該線程用到了p對象,
而如果當運行到該線程時,
且p.bFull為真時
該線程進行等待,讓其他線程運行

到這的思路如果沒有問題,
那麼我們假設
假設
p.bFull為假,
那麼會再往下運行
也就是設置姓名,性別,
此時p.bFull仍然為假

之後設置 p.bFull 為真
p.notify()
當設置p.bFull為真時,表示下次如果仍然是該線程執行,將會wait.
而p.notify()是為了解以p為鎖的線程,因為當前線程正在運行,所以當前線程肯定不需要解鎖,那可能需要被解鎖的,也就是Consumer對象的線程.

當前線程從開始運行到目前的位置,Consumer線程是一直在wait的,因為Consumer線程在while下面直接就synchronized (p)也就是這兩個線程同時只能一個線程運行.
也就是說,要麼這次運行Procer,要麼運行Consumer
按我上面說的,Procer的運行邏輯應該已經清楚了,而Consumer的線程運行邏輯跟Procer一樣,我就不多說了,

問題的關鍵在於
當Procer運行一次,之後Consumer運行一次,是比較好理解,交叉運行唄.
但如果Procer運行完,又運行了Procer線程,而沒有讓Consumer運行的時候,程序會怎麼運行?(反之一樣)
我下面來解釋.
當Procer運行一次,又運行了Procer時,這時因為沒有Consumer線程的介入
,p的bFull應該為真,
這時運行到
Procer線程的
if (p.bFull) {
try {
p.wait();
} catch (Exception e) {
}
時,因為p.bFull為真了,
所以運行下面的代碼,
也就是讓當前線程等待,而用來等待的鎖就是p
這時,當前線程等待了,
也就要執行Consumer線程了,也就是相當於強制切換線程
運行一次Consumer線程後,Procer仍然在等待,如果這樣,那就會仍然運行Consumer線程,根據邏輯,Consumer會像Procer一樣,由於
if(!p.bFull) {
try{p.wait(); } catch (Exception e) {} }
而等待
這樣兩個線程都等待了
(如果你問,當!p.bFull如果成立,那p.bFull就不成立,那Procer不是該運行了嗎?但是,我剛剛的假設是當Procer已經等待時,那麼Procer就不會因為p.bFull的改變而繼續運行了)

按上面所說,如果按這樣的邏輯,最終會導致兩個線程同時等待沒有解鎖,
為了解決這個問題,
就在程序的每個線程的
p.bFull = false;
後面,加上了
p.notify();
讓以p為鎖的線程解鎖等待.
這樣,就可以使程序的兩個線程來回切換了.

⑨ Java多線程中await和wait的區別

  1. 調用await/wait的時候卻釋放了其獲取的鎖並阻塞等待。

  2. await/wait,它會一直阻塞在條件隊列之上,之後某個線程調用對應的notify/signal方法,才會使得await/wait的線程回到就緒狀態,也是不一定立即執行。

  3. await/wait方法必須放在同步塊裡面,否則會產生運行時異常。

  4. wait方法是Object類的,await方法是Condition顯示條件隊列的。

⑩ java多線程怎樣讓一個線程睡眠

可以使用sleep()方法。

sleep()方法擁有一個參數,它控制睡眠的長短,以毫秒計算。sleep()方法會拋出InterruptedException,所以一定在try-catch塊裡面使用它。

示例代碼如下:

{
inti=0;

publicstaticvoidmain(String[]args){
Aa1=newA();
Aa2=newA();
a1.run();
a2.run();
}

publicvoidrun(){
while(++i<=100){
System.out.println(i);
try{
Thread.sleep(50);
}catch(Exceptione){
e.printStackTrace();
}
}
}
}

注意,sleep()方法並不保證線程醒來後進入運行,只能保證它進入就緒狀態。

閱讀全文

與java多線程ifwait相關的資料

熱點內容
騰訊雲輕量應用伺服器如何登陸 瀏覽:620
考研復試c語言編譯器 瀏覽:150
安卓的字體怎麼變粗 瀏覽:253
java錯誤無法載入主類 瀏覽:348
程序員考試考什麼文憑 瀏覽:883
pdf版破解 瀏覽:522
安卓系統如何重啟 瀏覽:174
小天才app鬧鍾怎麼改 瀏覽:962
司馬彥PDF 瀏覽:885
動力轉向編程 瀏覽:831
史瓦格期貨基本分析pdf 瀏覽:811
怎麼更改appid名字 瀏覽:235
抖音很解壓的東西 瀏覽:520
怎麼在app上進行機場升艙 瀏覽:133
fx3ga用什麼編程軟體 瀏覽:498
深度學習演算法樣本數量 瀏覽:966
電腦文件夾打開畫面塊狀 瀏覽:790
固態硬碟與機械盤的加密方法 瀏覽:634
unix編譯軟體 瀏覽:563
影視製作中西書局中央編譯出版社 瀏覽:822