生產者與消費者(二)---await與 signal

前面闡述了實現生產者與消費者問題的一種方式:wait() / notify()方法,本文繼續闡述多線程的經典問題---生產者與消費者的第二種方式:await() / signal()方法java

await() / signal()方法安全

在JDK5.0以後,Java提供了更加健壯的線程處理機制,包括同步、鎖定、線程池等,它們能夠實現更細粒度的線程控制。await()和signal()就是其中用來作同步的兩種方法,它們的功能基本上和wait() / nofity()相同,徹底能夠取代它們,可是它們和新引入的鎖定機制Lock直接掛鉤,具備更大的靈活性。經過在Lock對象上調用newCondition()方法,將條件變量和一個鎖對象進行綁定,進而控制併發程序訪問競爭資源的安全。多線程

緩衝區(倉庫):併發

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 {
    // 倉庫最大存儲量  
    private final int MAX_SIZE = 100;  
  
    // 倉庫存儲的載體  
    private LinkedList<Object> list = new LinkedList<Object>();  
  
    //
    private final Lock lock = new ReentrantLock();  
  
    // 倉庫滿的條件變量  
    private final Condition full = lock.newCondition();  
  
    // 倉庫空的條件變量  
    private final Condition empty = lock.newCondition();  
  
    // 生產num個產品  
    public void produce(int num){  
        // 得到鎖  
        lock.lock();  
  
        // 若是倉庫剩餘容量不足  
        while (list.size() + num > MAX_SIZE){  
            System.out.println("【要生產的產品數量】:" + num + "【庫存量】:" + list.size()+ "暫時不能執行生產任務!");  
            try{  
                // 因爲條件不知足,生產阻塞  
                full.await();  
            }  
            catch (InterruptedException e){  
                e.printStackTrace();  
            }  
        }  
  
        // 生產條件知足狀況下,生產num個產品  
        for (int i = 1; i <= num; ++i){  
            list.add(new Object());  
        }  
  
        System.out.println("【已經生產產品數】:" + num + "/t【現倉儲量爲】:" + list.size());  
  
        // 喚醒其餘全部線程  
        full.signalAll();  
        empty.signalAll();  
  
        // 釋放鎖  
        lock.unlock();  
    }  
  
    // 消費num個產品  
    public void consume(int num)  
    {  
        // 得到鎖  
        lock.lock();  
  
        // 若是倉庫存儲量不足  
        while (list.size() < num){  
            System.out.println("【要消費的產品數量】:" + num + "【庫存量】:" + list.size()+ "暫時不能執行生產任務!");  
            try{  
                // 因爲條件不知足,消費阻塞  
                empty.await();  
            }  
            catch (InterruptedException e){  
                e.printStackTrace();  
            }  
        }  
  
        // 消費條件知足狀況下,消費num個產品  
        for (int i = 1; i <= num; ++i){  
            list.remove();  
        }  
  
        System.out.println("【已經消費產品數】:" + num + "【現倉儲量爲】:" + 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;  
    }  
}

 

生產者:函數

public class Producer extends Thread {
     // 每次生產的產品數量  
    private int num;  
  
    // 所在放置的倉庫  
    private Storage storage;  
  
    // 構造函數,設置倉庫  
    public Producer(Storage storage){  
        this.storage = storage;  
    }  
  
    // 線程run函數  
    public void run(){  
        produce(num);  
    }  
  
    // 調用倉庫Storage的生產函數  
    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;  
    }  
    
}

 

消費者:測試

public class Consumer extends Thread {
    // 每次消費的產品數量  
    private int num;  
  
    // 所在放置的倉庫  
    private Storage storage;  
  
    // 構造函數,設置倉庫  
    public Consumer(Storage storage){  
        this.storage = storage;  
    }  
  
    // 線程run函數  
    public void run(){  
        consume(num);  
    }  
  
    // 調用倉庫Storage的生產函數  
    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;  
    }  
}

 

測試類:this

public class Test {
    public static void main(String[] args) {
        // 倉庫對象  
        Storage storage = new Storage();  
  
        // 生產者對象  
        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);  
  
        // 消費者對象  
        Consumer c1 = new Consumer(storage);  
        Consumer c2 = new Consumer(storage);  
        Consumer c3 = new Consumer(storage);  
  
        // 設置生產者產品生產數量  
        p1.setNum(10);  
        p2.setNum(10);  
        p3.setNum(10);  
        p4.setNum(10);  
        p5.setNum(10);  
        p6.setNum(10);  
        p7.setNum(80);  
  
        // 設置消費者產品消費數量  
        c1.setNum(50);  
        c2.setNum(20);  
        c3.setNum(30);  
  
        // 線程開始執行  
        c1.start();  
        c2.start();  
        c3.start();  
        p1.start();  
        p2.start();  
        p3.start();  
        p4.start();  
        p5.start();  
        p6.start();  
        p7.start();  
    }
}
相關文章
相關標籤/搜索