上一篇文章我們了解過了java有關(guān)線程的基本概念,有線程的屬性,線程可能處于的狀態(tài),還有線程的兩種創(chuàng)建的方式,最后還說了一個(gè)關(guān)鍵字synchronized,解決了高并發(fā)導(dǎo)致數(shù)據(jù)內(nèi)容不一致問題,本篇文章就介紹線程的中斷機(jī)制。
首先我們需要知道,java中的每個(gè)對(duì)象都是有內(nèi)部對(duì)象鎖的,其實(shí)每個(gè)java對(duì)象不止包含一個(gè)內(nèi)部對(duì)象鎖,還包含了一個(gè)等待隊(duì)列和一個(gè)條件隊(duì)列。
public synchronized void showName(){
************
}
這樣的一個(gè)被synchronized關(guān)鍵字修飾的方法,如果已經(jīng)有線程獲得了該對(duì)象的鎖,再有線程過來就會(huì)被阻塞并丟入等待隊(duì)列中。
private int count;public synchronized void showName(){ if(count==0){
wait();
}
}public synchronized void setName(){ if(count==0){
notifyAll();
}
}
而在上述的代碼段中,出現(xiàn)了兩個(gè)方法:wait和notifyAll。這兩個(gè)方法是成對(duì)出現(xiàn)的,wait主要作用是將當(dāng)前線程阻塞并且置入條件隊(duì)列上,notifyAll主要用于解放條件隊(duì)列上的所有線程,使他們可以再次競(jìng)爭(zhēng)處理機(jī)的調(diào)度以便運(yùn)行。
小結(jié)一下,以上就比較了等待隊(duì)列和條件隊(duì)列的作用和區(qū)別。等待隊(duì)列往往是因?yàn)橄胍暾?qǐng)的鎖已經(jīng)被別的線程占有了,需要置入等待隊(duì)列等待占有鎖的線程釋放鎖,然后接受處理機(jī)調(diào)度,被選中后方能獲得鎖并運(yùn)行。而條件隊(duì)列卻是一個(gè)已經(jīng)獲得鎖的線程在執(zhí)行過程中發(fā)現(xiàn)自己繼續(xù)運(yùn)行的條件不滿足(無法獲得某些需要的資源),程序無法繼續(xù)執(zhí)行下去了,于是調(diào)用wait方法阻塞自己并釋放外部對(duì)象鎖,置入條件隊(duì)列。
一旦占有某類資源的線程釋放該資源之后,調(diào)用notifyAll方法釋放所有在條件隊(duì)列上等待的線程,使他們重新接受處理機(jī)的挑選。如果被處理機(jī)選中運(yùn)行,就會(huì)從條件隊(duì)列出隊(duì),占有對(duì)象鎖,開始運(yùn)行。需要注意的是:wait和notifyAll方法只能在synchronized修飾的代碼塊中調(diào)用,否則就會(huì)拋出異常。其實(shí)原因也很簡(jiǎn)單,wait必須指定將當(dāng)前的線程掛在什么對(duì)象的條件隊(duì)列上,notifAll必須被指定釋放什么對(duì)象上的所有條件隊(duì)列中的線程。synchronized關(guān)鍵字是針對(duì)某個(gè)對(duì)象加鎖的,在其代碼塊中調(diào)用上述兩種方法就默認(rèn)操作