Ⅰ 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編程開發語言的過程中,我們掌握了線程與線程池等相關技術知識。今天,北大青鳥雲南計算機學院http://www.kmbdqn.cn/就關於線程安全問題給大家做一個簡單的喊枝答說明和介紹,一起來了解一下吧。
線程安全就是多線程訪問時,採用了加鎖機制,當一個線程訪問該類的某個數據時,進行保護,其他線程不能進行訪問直到該線程讀取完,其他線程才可使用。不會出現數據不一致或者數據污染。
線程不安全就是不提供數據訪問保護,有可能出現多個線程先後更改數據造成所得到的數據是臟數據搭罩。
什麼時候考慮到線程安全:
一個對象是否需要線程安全,取決於該對象是否被多線程訪問。這指的是程序中訪問對象的方式,而不是對象要實現的功能。要使得對象是線程安全的,要採用同步機制來協同對對象可變狀態的訪問。Java常用的同步機制是Synchronized,還包括volatile類型的變數,顯示鎖以及原子變數。在多個線程中,當它們同時訪問同個類時,每次執行的結果和單線程結果一致,且變數值跟預期一致,這個類則是線程安全的。
鎖的特性
鎖機制的兩種特性:
互斥性:即同一時間只允許一個線程持有某個對象的鎖,通過這種特性來實現多線程中的協調機制,這樣在同一時間只有一個線程對需同步的代碼塊(復合操作)進行訪問。互斥性我們也往往稱為操作的原子性。
可見性:必須確保在鎖被釋放之前,對共享變數所做的修改,對於隨後獲得該鎖的另一個線程是可見的,否則另一個線程可能是在本地緩存的某個副本上繼續操作從而引起不一致。
掛起、休眠、阻塞和非阻塞
掛起:當線程被掛起時,其會失去CPU的使用時間,直到被其他線程(用戶線程或調試線程)喚醒。
休眠:同樣是會失去CPU的使用時間,但是在過了指定的休眠時間之後,它會自動激活,無需喚醒(整個喚醒表面看是自動的,但實際上也得有守護線程去喚醒,只是不需編程者手動干預)。
阻塞:在線程執行時,所需要的資源不能得到,則線程被掛起,直到滿足可操作的條件。
非阻塞:在線程執行時,鄭慧所需要的資源不能得到,則線程不是被掛起等待,而是繼續執行其餘事情,等待條件滿足了後,收到了通知(同樣是守護線程去做)再執行。
Ⅲ JAVA裡面線程的阻塞狀態和掛起狀態'的區別
阻塞就是路給堵死了,隨便等多久都不痛。。。
掛起就是等一段時間就會通!
Ⅳ java中如何啟動一個新的線程
java開啟新線程的三種方法:
方法1:繼承Thread類
1):定義一個繼承自Java.lang.Thread類的類A.
2):覆蓋A類Thread類中的run方法。
3):我們編寫需要在run方法中執行的操作:run方法中的代碼,線程執行體。
4):在main方法(線程)中,創建一個線程對象並啟動線程。
(1)創建線程類對象:
A類 a = new A類();
(2)調用線程對象的start方法:
a.start();//啟動一個線程
注意:不要調用run方法。如果run方法被稱為對象調用方法,則仍然只有一個線程,並且沒有啟動新線程。
創建啟動線程實例:
(4)java掛起線程擴展閱讀:
啟動新線程的兩種方式對比
繼承方式:
1):從設計上分析,Java中類是單繼承的,如果繼承了Thread了,該類就不能再有其他的直接父類了.
2):從操作上分析,繼承方式更簡單,獲取線程名字也簡單.(操作上,更簡單)
3):從多線程共享同一個資源上分析,繼承方式不能做到.
實現方式:
1):從設計上分析,Java中類可以多實現介面,此時該類還可以繼承其他類,並且還可以實現其他介面,設計更為合理.
2):從操作上分析,實現方式稍微復雜點,獲取線程名字也比較復雜,得使用Thread.currentThread()來獲取當前線程的引用.
3):從多線程共享同一個資源上分析,實現方式可以做到(是否共享同一個資源).
補充:實現方式獲取線程名字:
String name = Thread.currentThread().getName();
Ⅳ javathreat.stop報錯
javathreat.stop報錯
以下核陸包含javathreadstop報錯的結果,仍然搜索javathreatstop報錯
java線程stop方法不能用 - java線程無法正常停止總結 - masaki叔還是這么可 ...
1. 死鎖。這個很容易藉助jdk提供的工具定位到對應的代碼位置,使用jps 然後jstack id。就能夠看到BEBLOCK狀態,並有對應的代碼堆棧。
2. 線程掛起。並不是死鎖現象,而是線歷氏旦程掛起,線程狀態時RUNNING狀態,這中就不好定位了,因為線程狀態一直時RUNNING狀態,很容易就當成服務的正常狀態了。針對這種問題
3. 自己開辟的線程不是肢擾後台線程,該線程一直不會停止
Ⅵ java關於等待線程結束的問題!
簡單地可以使用 Thread.join() 方法來等待線程結束,例如這樣修改一下:
Threadt=局悔newThread(){
//同團臘散原來的run()
};
t.start();
//調用這個方法,會掛起當前線程直至線程t結束
t.join();
join()方法的文檔是這么寫的: Waits for this thread to die.
也可以用wait/notify或mutex等機制來對兩個線程進行同步,稍微復雜一點,例如使用 wait/notify:
newThread(){
publicvoidrun(){
//同原來的代碼,加上以下代碼用於同步
synchronized(results){
results.notifyAll();
}
}
}.start();
//通過以下代碼掛起當前線程,等待其他線程通知
synchronized(results){
results.wait();
}
以供參考。
同 i178269245 所說,等待線程結束勢必要掛起當前線程,也就沒必要用線程了,也許需要重新考慮一下這種實現方式塌氏。
Ⅶ java 中線程睡眠和掛起區別
wait是進入隊桐畢列等待獲取鎖,notify是橘凳在已經佔有鎖的時候釋放鎖,並通知wait隊列里的某一個線程起來圓輪旅去獲取鎖。
Ⅷ 在Java中什麼叫一個線程被掛起
就是說你自己定義了一個線程事件 你需要它運行 當它運行一段時間後為了實現汪激某項功能你需要它停止 或者休眠 比如stop() sleep()方螞租法 我們叫線悶陵兆程掛起
Ⅸ java線程掛起是什麼意思
資源仍被佔用,不被是釋放。