生産者和消費者是多線程經典的問題,生産者和消費者問題的核心是同步的問題,同步問題的核心是要保證同一個資源被多個線程并發通路時的完整性,常用的方法是采用信号或加鎖機制,保證資源在任一時刻隻能被一個線程通路。這一問題用java來實作的話主要有4種方式。1.wait()/notify();2.await()/signal(); 3.blockingquene 4.pipedinputstream/pipedoutputstream
下面分别來實作。
wait()方法:當緩沖區已空/滿時,生産者/消費者停止自己的執行,放棄鎖,使自己處于等待狀态,讓其他線程執行。
notify()方法:當生産者/消費者向緩沖區放入/取出一個産品時,向其他等待的線程發出可執行的通知,同時放棄鎖,使自己處于等待狀态。
下面看看代碼實作:
首先定義商店類:
定義生産者類
定義消費者類:
建立測試類:
該方法中用到的幾個類做一下說明:
reentrantlock():一個可重入的互斥鎖lock,它具有與使用 synchronized 方法和語句所通路的隐式螢幕鎖相同的一些基本行為和語義,但功能更強大。 reentrantlock 将由最近成功獲得鎖,并且還沒有釋放該鎖的線程所擁有。當鎖沒有被另一個線程所擁有時,調用lock
的線程将成功擷取該鎖并傳回。如果目前線程已經擁有該鎖,此方法将立即傳回。可以使用 isheldbycurrentthread()和
getholdcount()方法來檢查此情況是否發生。
condition():将 object螢幕方法(wait、notify和
notifyall)分解成截然不同的對象,以便通過将這些對象與任意lock 實作組合使用,為每個對象提供多個等待 set(wait-set)。其中,lock替代了
synchronized 方法和語句的使用,condition替代了 object 螢幕方法的使用。
條件(也稱為條件隊列 或條件變量)為線程提供了一個含義,以便在某個狀态條件現在可能為 true 的另一個線程通知它之前,一直挂起該線程(即讓其“等待”)。因為通路此共享狀态資訊發生在不同的線程中,是以它必須受保護,是以要将某種形式的鎖與該條件相關聯。等待提供一個條件的主要屬性是:以原子方式釋放相關的鎖,并挂起目前線程,就像 object.wait 做的那樣。
condition執行個體實質上被綁定到一個鎖上。要為特定
lock 執行個體獲得 condition 執行個體,請使用其
newcondition()方法。
定義倉庫的代碼為:
生産者、消費者和測試類的代碼儲存不變