java實現生產者/消費者問題

 問題描述:一個生產者在生產產品,這些產品將提供給若干個消費者去消費,爲了使生產者和消費者可以併發執行,在二者之間設置一個具備多個緩衝區的緩衝池,生產者將生產的產品放入一個緩衝區內,消費者能夠從緩衝區中取走產品進行消費;緩存

  生產者和消費者必須保持同步,不容許消費者到一個空的緩衝區中取產品,也不容許生產者向一個已經投放了產品的緩衝區再次投放產品;併發

 

代碼實現:函數

  1).wait()和notify()方式來實現this

public class Storage{
    
    //緩衝區最大承載量
    private final int MAX_SIZE = 100;

    //緩衝區存儲的載體
    private LinkedList<Object> list = new LinkedList<Object>();

    /**
    *
    *   生產num個產品
    */
    public void produce(int num){
        //獲取鎖
        synchronized(list){
            //緩存區剩餘容量不足
            while(list.size() + num > MAX_SIZE){
                System.out.println("要生產的產品數量:"+num+"/t 庫存量:"+list.size+"/t 暫時不能執行生產任務!");
                try{
                    //因爲條件不知足,生產阻塞
                    list.wait()
                }catch(InterruptedException e){
                     e.printStackTrace();
                }
            }
            
            //在生產條件知足狀況下,生產num歌產品
            for(int i=1;i<=num;++i){
                list.add(new Object());
            }
            System.out.println("已經生產產品數:"+num+"/t 現倉儲量爲:"+list.size());
            list.notifyAll();
        }
    }  
    
    /**
    *
    *   消費num個產品
    */
    public void consume(int num){
        //獲取鎖
        synchronized(list){
            //緩存區剩餘容量不足
            while(list.size() < num){
                System.out.println("要消費的產品數量:"+num+"/t 庫存量:"+list.size+"/t 暫時不能執行消費任務!");
                try{
                    //因爲條件不知足,消費阻塞
                    list.wait()
                }catch(InterruptedException e){
                     e.printStackTrace();
                }
            }
            
            //在生產條件知足狀況下,生產num歌產品
            for(int i=1;i<=num;++i){
                list.remove();
            }
            System.out.println("已經消費產品數:"+num+"/t 現倉儲量爲:"+list.size());
            list.notifyAll();
        }
    }

    //list getter//setter
    //MAX_SIZE getter
} 
public class Producer extends Thread{
    //每次生產的產品數量
    private int num;
    //倉庫對象
    private Storage storage;

    //構造函數,設置倉庫
    public Producer(Storage storage){
        this.storage = storage;
    }

    //線程run函數
    public void run(){
        produce();
    }

    //調用倉庫的生產方法
    public void produce(){
        storage.produce();
    }

    //num storage的getter(),setter()方法
}
/**
*
*  消費者線程類
*/
public class Consumer extends Thread{
    private int num;
    private Storage storage;
    public void Consumer(Storage storage){
        this.storage = storage;
    }
    public void run(){
        consume();
    }

    public void consume(){
        storage.consume();
    }

    //num和storage的getter(),setter()方法
}
public class Test{
    public static void main(String args[]){
        //倉庫對象
        Storage storage = new Storage();
        //生產者對象
        Producer p1 = new Producer();
        Producer p2 = new Producer();
        Producer p3 = new Producer();
        Producer p4 = new Producer();
        Producer p5 = new Producer();
        Producer p6 = new Producer();
        //消費者對象
        Consumer c1 =  new Consumer();
        Consumer c2 =  new Consumer();
        Consumer c3 =  new Consumer();
        Consumer c4 =  new Consumer();
        Consumer c5 =  new Consumer();

        //設置生產者生產數量
        p1.setNum(10);
        p2.setNum(10);
        p3.setNum(10);
        p4.setNum(40);
        p5.setNum(50);
        p6.setNum(30);

        //設置消費者消費數量
        c1.setNum(10);
        c2.setNum(20);
        c3.setNum(10);
        c4.setNum(30);
        c5.setNum(10);

        //執行線程
        p1.start();
        p2.start();
        p3.start();
        p4.start();
        p5.start();
        p6.start();
        c1.start();
        c2.start();
        c3.start();
        c4.start();
        c5.start();
    }
}

 

  2).await()和signal()方式實現spa

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+"/t 庫存量:"+list.size+"/t 暫時不能執行生產任務!");
            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+"/t 庫存量:"+list.size+"/t 暫時不能執行消費任務!");
            try{
                //因爲條件不知足,消費阻塞
                empty.await()
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
            
        //在生產條件知足狀況下,生產num歌產品
        for(int i=1;i<=num;++i){
            list.remove();
        }
        System.out.println("已經消費產品數:"+num+"/t 現倉儲量爲:"+list.size());
        full.signalAll();
        empty.signalAll();
        //釋放鎖
        lock.unlock();
    }

    //list getter//setter
    //MAX_SIZE getter
} 

 

  3).BlockingQueue阻塞隊列來實現線程

public class Storage{
    
    //緩衝區最大承載量
    private final int MAX_SIZE = 100;

    //緩衝區存儲的載體
    private LinkedBlockingQueue<Object> list = new LinkedBlockingQueue<Object>(100);

    /**
    *
    *   生產num個產品
    */
    public void produce(int num){

        //緩存區剩餘容量不足
        while(list.size() == MAX_SIZE){
            System.out.println(「庫存量:"+MAX_SIZE+"/t 暫時不能執行生產任務!");
        }
            
        //在生產條件知足狀況下,生產num歌產品
        for(int i=1;i<=num;++i){
            try{
                list.put(new Object());//容量達到最大時候,自動阻塞
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
        System.out.println("現倉儲量爲:"+list.size());
    }  
    
    /**
    *
    *   消費num個產品
    */
    public void consume(int num){
        
        //緩存區剩餘容量不足
        while(list.size() == 0){
            System.out.println("庫存量:"+0+"/t 暫時不能執行消費任務!");
        }
            
        //在生產條件知足狀況下,生產num歌產品
        for(int i=1;i<=num;++i){
            try{
                list.take();//容量爲0時,自動阻塞
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
        System.out.println("現倉儲量爲:"+list.size());

    }

    //list getter//setter
    //MAX_SIZE getter
} 
相關文章
相關標籤/搜索