當線程在系統內運行時,線程的調度具有一定的透明性,程序通常無法準確控制線程的輪換執行,但Java也提供了一些機制來保證線程協調運行。
1 傳統的線程通信
可藉助Object類提供的wait()、notify()和notifyAll()三個方法,注意這三個方法不屬於Thread類,而是屬於Object類,另外這三個方法必須由同步監視器(鎖)對象來調用。對於同步方法,鎖對象就是該類的默認實例this;對於同步代碼塊,鎖對象就是synchronized後括號裏的對象。
2 使用Condition控制線程通信
如果程序不適用synchronized關鍵字來保證同步,而是直接使用Lock對象來保證同步,則系統中不存在隱式的同步監視器,也就不能使用wait()、notify()和notifyAll()方法進行線程通信了。
當使用Lock對象來保證同步時,Java提供了一個Condition類來保持協調,使用Condition可以讓那些已經得到Lock對象卻無法繼續執行的線程釋放Lock對象,Condition對象也可以喚醒其他處於等待的線程。
Condition實例被綁定在一個Lock對象上,要獲得特定的Lock實例的Condition實例,調用Lock對象的newCondition()方法即可。Condition類提供了三個方法:await()、signal()和signalAll()。
3 使用阻塞隊列控制線程通信
Java 5 提供了一個BlockingQueue接口,雖然BlockingQueue也是Queue的子接口,但它的主要用途並不是作爲容器,而是作爲線程同步的工具。
BlockingQueue具有一個特徵:當生產者線程試圖向BlockingQueue中放入元素時,如果該隊列已滿,則該線程被阻塞;當消費者線程試圖從BlockingQueue中取出元素時,如果該隊列已空,則該線程被阻塞。對應提供了兩個支持阻塞的方法,put(E e)和take()。
BlockingQueue包含5個實現類:
(1)ArrayBlockingQueue是基於數組實現的BlockingQueue隊列;
(2)LinkedBlockingQueue是基於鏈表實現的BlockingQueue對列;
(3)PriorityBlockingQueue是可以定製排序的非標準阻塞隊列;
(4)SynchronousQueue:同步隊列;
(5)DelayQueue底層是基於PriorityBlockingQueue實現。