java實現生產者消費者問題

來源:互聯網
上載者:User

標籤:java   多線程   生產者消費者   

生產者消費者問題(英語:Producer-consumer problem),也稱有限緩衝問題(英語:Bounded-buffer problem),是一個多線程同步問題的經典案例。該問題描述了兩個共用固定大小緩衝區的線程——即所謂的“生產者”和“消費者”——在實際運行時會發生的問題。生產者的主要作用是產生一定量的資料放到緩衝區中,然後重複此過程。與此同時,消費者也在緩衝區消耗這些資料。該問題的關鍵就是要保證生產者不會在緩衝區滿時加入資料,消費者也不會在緩衝區中空時消耗資料。

引言

  生產者和消費者問題是執行緒模式中的經典問題:生產者和消費者在同一時間段內共用同一個儲存空間,如所示,生產者向空間裡存放資料,而消費者取用資料,如果不加以協調可能會出現以下情況:

生產者消費者圖

  儲存空間已滿,而生產者佔用著它,消費者等著生產者讓出空間從而去除產品,生產者等著消費者消費產品,從而向空間中添加產品。互相等待,從而發生死結。

JAVA解決執行緒模式的三種方式

  1、wait()和notify()


import java.util.LinkedList;public class ProducerConsumer {    private LinkedList<Object> storeHouse = new LinkedList<Object>();    private int MAX = 10;    public ProducerConsumer() {    }    public void start() {        new Producer().start();        new Comsumer().start();    }    class Producer extends Thread {        public void run() {            while (true) {                synchronized (storeHouse) {                    try {                        while (storeHouse.size() == MAX) {                            System.out.println("storeHouse is full , please wait");                            storeHouse.wait();                        }                        Object newOb = new Object();                        if (storeHouse.add(newOb)) {                            System.out.println("Producer put a Object to storeHouse");                            Thread.sleep((long) (Math.random() * 3000));                            storeHouse.notify();                        }                    } catch (InterruptedException ie) {                        System.out.println("producer is interrupted!");                    }                }            }        }    }    class Comsumer extends Thread {        public void run() {            while (true) {                synchronized (storeHouse) {                    try {                        while (storeHouse.size() == 0) {                            System.out.println("storeHouse is empty , please wait");                            storeHouse.wait();                        }                        storeHouse.removeLast();                        System.out.println("Comsumer get  a Object from storeHouse");                        Thread.sleep((long) (Math.random() * 3000));                        storeHouse.notify();                    } catch (InterruptedException ie) {                        System.out.println("Consumer is interrupted");                    }                }            }        }    }    public static void main(String[] args) throws Exception {        ProducerConsumer pc = new ProducerConsumer();        pc.start();    }}



 

  2、await()和signal(),即線程鎖的方式


package sort;import java.util.LinkedList;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ProducerConsumer {    private LinkedList<Object> myList = new LinkedList<Object>();    private int MAX = 10;    private final Lock lock = new ReentrantLock();    private final Condition full = lock.newCondition();    private final Condition empty = lock.newCondition();    public ProducerConsumer() {    }    public void start() {        new Producer().start();        new Consumer().start();    }    public static void main(String[] args) throws Exception {        ProducerConsumer s2 = new ProducerConsumer();        s2.start();    }    class Producer extends Thread {        public void run() {            while (true) {                lock.lock();                try {                    while (myList.size() == MAX) {                        System.out.println("warning: it's full!");                        full.await();                    }                    Object o = new Object();                    if (myList.add(o)) {                        System.out.println("Producer: " + o);                        empty.signal();                    }                } catch (InterruptedException ie) {                    System.out.println("producer is interrupted!");                } finally {                    lock.unlock();                }            }        }    }    class Consumer extends Thread {        public void run() {            while (true) {                lock.lock();                try {                    while (myList.size() == 0) {                        System.out.println("warning: it's empty!");                        empty.await();                    }                    Object o = myList.removeLast();                    System.out.println("Consumer: " + o);                    full.signal();                } catch (InterruptedException ie) {                    System.out.println("consumer is interrupted!");                } finally {                    lock.unlock();                }            }        }    }}

 

  3、阻塞隊列的方式


import java.util.concurrent.*;public class ProducerConsumer {    // 建立一個阻塞隊列    private LinkedBlockingQueue<Object> queue = new LinkedBlockingQueue<Object>(10);    public ProducerConsumer() {    }    public void start() {        new Producer().start();        new Consumer().start();    }    public static void main(String[] args) throws Exception {        ProducerConsumer s3 = new ProducerConsumer();        s3.start();    }    class Producer extends Thread {        public void run() {            while (true) {                try {                    Object o = new Object();                    // 取出一個對象                    queue.put(o);                    System.out.println("Producer: " + o);                } catch (InterruptedException e) {                    System.out.println("producer is interrupted!");                }                // }            }        }    }    class Consumer extends Thread {        public void run() {            while (true) {                try {                    // 取出一個對象                    Object o = queue.take();                    System.out.println("Consumer: " + o);                } catch (InterruptedException e) {                    System.out.println("producer is interrupted!");                }                // }            }        }    }}

結論

  三種方式原理一致,都是對獨佔空間加鎖,阻塞和喚醒線程,第一種方式比較傳統,第三種方式最簡單,只需儲存和取用,線程同步的操作交由LinkedBlockingQueue全權處理。

java實現生產者消費者問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.