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