生产者与消费者(二)---await与 signal
前面闡述了實(shí)現(xiàn)生產(chǎn)者與消費(fèi)者問(wèn)題的一種方式:wait() / notify()方法,本文繼續(xù)闡述多線程的經(jīng)典問(wèn)題---生產(chǎn)者與消費(fèi)者的第二種方式:await() / signal()方法。
await() / signal()方法
在JDK5.0之后,Java提供了更加健壯的線程處理機(jī)制,包括同步、鎖定、線程池等,它們可以實(shí)現(xiàn)更細(xì)粒度的線程控制。await()和signal()就是其中用來(lái)做同步的兩種方法,它們的功能基本上和wait() / nofity()相同,完全可以取代它們,但是它們和新引入的鎖定機(jī)制Lock直接掛鉤,具有更大的靈活性。通過(guò)在Lock對(duì)象上調(diào)用newCondition()方法,將條件變量和一個(gè)鎖對(duì)象進(jìn)行綁定,進(jìn)而控制并發(fā)程序訪問(wèn)競(jìng)爭(zhēng)資源的安全。
緩沖區(qū)(倉(cāng)庫(kù)):
import java.util.LinkedList; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;public class Storage {// 倉(cāng)庫(kù)最大存儲(chǔ)量 private final int MAX_SIZE = 100; // 倉(cāng)庫(kù)存儲(chǔ)的載體 private LinkedList<Object> list = new LinkedList<Object>(); // 鎖 private final Lock lock = new ReentrantLock(); // 倉(cāng)庫(kù)滿的條件變量 private final Condition full = lock.newCondition(); // 倉(cāng)庫(kù)空的條件變量 private final Condition empty = lock.newCondition(); // 生產(chǎn)num個(gè)產(chǎn)品 public void produce(int num){ // 獲得鎖 lock.lock(); // 如果倉(cāng)庫(kù)剩余容量不足 while (list.size() + num > MAX_SIZE){ System.out.println("【要生產(chǎn)的產(chǎn)品數(shù)量】:" + num + "【庫(kù)存量】:" + list.size()+ "暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!"); try{ // 由于條件不滿足,生產(chǎn)阻塞 full.await(); } catch (InterruptedException e){ e.printStackTrace(); } } // 生產(chǎn)條件滿足情況下,生產(chǎn)num個(gè)產(chǎn)品 for (int i = 1; i <= num; ++i){ list.add(new Object()); } System.out.println("【已經(jīng)生產(chǎn)產(chǎn)品數(shù)】:" + num + "/t【現(xiàn)倉(cāng)儲(chǔ)量為】:" + list.size()); // 喚醒其他所有線程 full.signalAll(); empty.signalAll(); // 釋放鎖 lock.unlock(); } // 消費(fèi)num個(gè)產(chǎn)品 public void consume(int num) { // 獲得鎖 lock.lock(); // 如果倉(cāng)庫(kù)存儲(chǔ)量不足 while (list.size() < num){ System.out.println("【要消費(fèi)的產(chǎn)品數(shù)量】:" + num + "【庫(kù)存量】:" + list.size()+ "暫時(shí)不能執(zhí)行生產(chǎn)任務(wù)!"); try{ // 由于條件不滿足,消費(fèi)阻塞 empty.await(); } catch (InterruptedException e){ e.printStackTrace(); } } // 消費(fèi)條件滿足情況下,消費(fèi)num個(gè)產(chǎn)品 for (int i = 1; i <= num; ++i){ list.remove(); } System.out.println("【已經(jīng)消費(fèi)產(chǎn)品數(shù)】:" + num + "【現(xiàn)倉(cāng)儲(chǔ)量為】:" + list.size()); // 喚醒其他所有線程 full.signalAll(); empty.signalAll(); // 釋放鎖 lock.unlock(); } // set/get方法 public int getMAX_SIZE() { return MAX_SIZE; } public LinkedList<Object> getList() { return list; } public void setList(LinkedList<Object> list) { this.list = list; } }?
生產(chǎn)者:
public class Producer extends Thread {// 每次生產(chǎn)的產(chǎn)品數(shù)量 private int num; // 所在放置的倉(cāng)庫(kù) private Storage storage; // 構(gòu)造函數(shù),設(shè)置倉(cāng)庫(kù) public Producer(Storage storage){ this.storage = storage; } // 線程run函數(shù) public void run(){ produce(num); } // 調(diào)用倉(cāng)庫(kù)Storage的生產(chǎn)函數(shù) public void produce(int num){ storage.produce(num); } // get/set方法 public int getNum() { return num; } public void setNum(int num) { this.num = num; } public Storage getStorage() { return storage; } public void setStorage(Storage storage) { this.storage = storage; } }?
消費(fèi)者:
public class Consumer extends Thread {// 每次消費(fèi)的產(chǎn)品數(shù)量 private int num; // 所在放置的倉(cāng)庫(kù) private Storage storage; // 構(gòu)造函數(shù),設(shè)置倉(cāng)庫(kù) public Consumer(Storage storage){ this.storage = storage; } // 線程run函數(shù) public void run(){ consume(num); } // 調(diào)用倉(cāng)庫(kù)Storage的生產(chǎn)函數(shù) public void consume(int num){ storage.consume(num); } // get/set方法 public int getNum() { return num; } public void setNum(int num) { this.num = num; } public Storage getStorage() { return storage; } public void setStorage(Storage storage) { this.storage = storage; } }?
測(cè)試類:
public class Test {public static void main(String[] args) {// 倉(cāng)庫(kù)對(duì)象 Storage storage = new Storage(); // 生產(chǎn)者對(duì)象 Producer p1 = new Producer(storage); Producer p2 = new Producer(storage); Producer p3 = new Producer(storage); Producer p4 = new Producer(storage); Producer p5 = new Producer(storage); Producer p6 = new Producer(storage); Producer p7 = new Producer(storage); // 消費(fèi)者對(duì)象 Consumer c1 = new Consumer(storage); Consumer c2 = new Consumer(storage); Consumer c3 = new Consumer(storage); // 設(shè)置生產(chǎn)者產(chǎn)品生產(chǎn)數(shù)量 p1.setNum(10); p2.setNum(10); p3.setNum(10); p4.setNum(10); p5.setNum(10); p6.setNum(10); p7.setNum(80); // 設(shè)置消費(fèi)者產(chǎn)品消費(fèi)數(shù)量 c1.setNum(50); c2.setNum(20); c3.setNum(30); // 線程開(kāi)始執(zhí)行 c1.start(); c2.start(); c3.start(); p1.start(); p2.start(); p3.start(); p4.start(); p5.start(); p6.start(); p7.start(); } }?
轉(zhuǎn)載于:https://www.cnblogs.com/Kevin-mao/p/5950758.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的生产者与消费者(二)---await与 signal的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python基础教程学习笔记十二
- 下一篇: 【python】lxml处理命名空间