
Java、Thread、線程阻塞、method
解析Java Thread 類方法
-
sleep()
-
suspend()
-
resume()
-
yield()
-
wait()
-
notify()
線程的阻塞
線程的阻塞發(fā)生原因是什么?
- 為了解決對
共享存儲區(qū)的訪問沖突,Java 引入了同步機制,現(xiàn)在讓我們來考察多個線程對共享資源的訪問,顯然同步機制已經(jīng)不夠了,因為在任意時刻所要求的資源不一定已經(jīng)準備好了被訪問,反過來,同一時刻準備好了的資源也可能不止一個。為了解決這種情況下的訪問控制問題,Java 引入了對阻塞機制的支持。
什么是線程阻塞?
- 阻塞指的是暫停一個線程的執(zhí)行以等待某個條件發(fā)生(如某資源就緒),學過操作系統(tǒng)的同學對它一定已經(jīng)很熟悉了。Java 提供了大量方法來支持阻塞,下面讓我們逐一分析。
Thread方法解析
sleep() 方法:
sleep()允許 指定以毫秒為單位的一段時間作為參數(shù),它使得線程在指定的時間內(nèi)進入阻塞狀態(tài),不能得到CPU 時間,指定的時間一過,線程重新進入可執(zhí)行狀態(tài)。 典型的sleep()被用在等待某個資源就緒的情形:測試發(fā)現(xiàn)條件不滿足后,讓線程阻塞一段時間后重新測試,直到條件滿足為止。suspend() 和 resume() 方法:兩個方法配套使用,
suspend()使得線程進入阻塞狀態(tài),并且不會自動恢復(fù),必須其對應(yīng)的resume()被調(diào)用,才能使得線程重新進入可執(zhí)行狀態(tài)。典型的suspend()和resume()被用在等待另一個線程產(chǎn)生的結(jié)果的情形:測試發(fā)現(xiàn)結(jié)果還沒有產(chǎn)生后,讓線程阻塞,另一個線程產(chǎn)生了結(jié)果后,調(diào)用resume()使其恢復(fù)。yield() 方法:
yield()使得線程放棄當前分得的 CPU 時間,但是不使線程阻塞,即線程仍處于可執(zhí)行狀態(tài),隨時可能再次分得 CPU 時間。調(diào)用yield()的效果等價于調(diào)度程序認為該線程已執(zhí)行了足夠的時間從而轉(zhuǎn)到另一個線程.wait() 和 notify() 方法:兩個方法配套使用,
wait()使得線程進入阻塞狀態(tài),它有兩種形式,一種允許 指定以毫秒為單位的一段時間作為參數(shù),另一種沒有參數(shù),前者當對應(yīng)的notify()被調(diào)用或者超出指定時間時線程重新進入可執(zhí)行狀態(tài),后者則必須對應(yīng)的notify()被調(diào)用。
方法概述
首先,前面敘述的所有方法都隸屬于
Thread類,但是這一對卻直接隸屬于Object類,也就是說,所有對象都擁有這一對方法。初看起來這十分不可思議,但是實際上卻是很自然的,因為這一對方法阻塞時要釋放占用的鎖,而鎖是任何對象都具有的,調(diào)用任意對象的wait()方法導(dǎo)致線程阻塞,并且該對象上的鎖被釋放。而調(diào)用 任意對象的notify()方法則導(dǎo)致因調(diào)用該對象的wait()方法而阻塞的線程中隨機選擇的一個解除阻塞(但要等到獲得鎖后才真正可執(zhí)行)。其次,前面敘述的所有方法都可在任何位置調(diào)用,但是這一對方法卻必須在
synchronized方法或塊中調(diào)用,理由也很簡單,只有在synchronized方法或塊中當前線程才占有鎖,才有鎖可以釋放。同樣的道理,調(diào)用這一對方法的對象上的鎖必須為當前線程所擁有,這樣才有鎖可以釋放。因此,這一對方法調(diào)用必須放置在這樣的synchronized方法或塊中,該方法或塊的上鎖對象就是調(diào)用這一對方法的對象。若不滿足這一條件,則程序雖然仍能編譯,但在運行時會出現(xiàn)IllegalMonitorStateException異常。
關(guān)于 wait() 和 notify() 方法最后再說明兩點:
調(diào)用
notify()方法導(dǎo)致解除阻塞的線程是從因調(diào)用該對象的wait()方法而阻塞的線程中隨機選取的,我們無法預(yù)料哪一個線程將會被選擇,所以編程時要特別小心,避免因這種不確定性而產(chǎn)生問題。除了
notify(),還有一個方法notifyAll()也可起到類似作用,唯一的區(qū)別在于,調(diào)用 notifyAll() 方法將把因調(diào)用該對象的 wait() 方法而阻塞的所有線程一次性全部解除阻塞。當然,只有獲得鎖的那一個線程才能進入可執(zhí)行狀態(tài)。