生產者和消費者問題學習以及Java實現

來源:互聯網
上載者:User

標籤:sync   log   使用   containe   col   obj   寫法   start   notify   

 

在電腦領域中,生產者-消費者問題(也叫bounded-buffer問題)是一類很經典的多進程同步問題。該問題描述了兩類進程,即生產者進程和消費者進程,它們共用一個固定大小的緩衝區作為隊列。生產者的任務是產生資料,並放到緩衝區中;同時消費者會消費資料(或者說將資料從緩衝區中移走)。每次生產或者消費資料的個數都是一個。在解決該問題時要確保當緩衝區滿了之後,不會再向其中添加資料;當緩衝區為空白的時候,消費者不能從中提取資料。

 

當緩衝區滿了時,生產者要麼進入休眠狀態,要麼丟棄產生的資料。等到下次消費者從緩衝區中移走一項資料之後,要通知生產者繼續往緩衝區中添加資料。同樣的,當消費者發現緩衝區為空白時,消費者進入休眠狀態。當生產者往緩衝區中寫入資料之後,生產者要喚醒消費者來消費資料。該問題可以通過處理序間通訊來解決,典型的做法是使用訊號量。如果該問題解決不當會導致死結,即生產者和消費者都處於等待喚醒的狀態。

 

這裡參考了網上的寫法,寫了一個很簡單的版本。有4個檔案:

1. 容器,Container.java

2. 生產者,Producer.java

3. 消費者,Consumer.java

4. 測試檔案,Test.java

 

Producer.java

package com.tuhooo.practice.pcmodel;/** * 生產者 */public class Producer implements Runnable {    private Container<Integer> container;    private Object producerMonitor;    private Object consumerMonitor;    Producer(Container<Integer> container, Object producerMonitor, Object consumerMonitor) {        this.container = container;        this.producerMonitor = producerMonitor;/*生產者的鎖*/        this.consumerMonitor = consumerMonitor;/*消費者的鎖*/    }    public void run() {        while (true) {            produce();        }    }    private void produce() {        if (container.isFull()) {            synchronized (producerMonitor) {                try {                    if (container.isFull()) {                        producerMonitor.wait();                    }                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        } else {            synchronized (producerMonitor) {                if (!container.isFull()) {                    container.add(0);                    try {                        Thread.currentThread().sleep(1000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    System.out.println("生產者【" + Thread.currentThread().getId() + "】生產了一個, 一共" + container.getSize() + "個");                }            }        }        if (!container.isEmpty()) {            synchronized (consumerMonitor) {                if (!container.isEmpty()) {                    consumerMonitor.notify();                }            }        }    }}

Consumer.java

package com.tuhooo.practice.pcmodel;/** * 消費者 */public class Consumer implements Runnable {    private Container<Integer> container;    private Object producerMonitor;    private Object consumerMonitor;    Consumer(Container<Integer> container, Object producerMonitor, Object consumerMonitor) {        this.container = container;        this.producerMonitor = producerMonitor;/*生產者的鎖*/        this.consumerMonitor = consumerMonitor;/*消費者的鎖*/    }        public void run() {        while (true) {            consume();        }    }    /*消費方法怎麼寫*/    private void consume() {        if (container.isEmpty()) {            //消費者掛起            synchronized (consumerMonitor) {                try {                    if (container.isEmpty()) {                        consumerMonitor.wait();                    }                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        } else {            synchronized (consumerMonitor) {                if (!container.isEmpty()) {                    container.get();                    try {                        Thread.currentThread().sleep(500);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                    System.out.println("消費者【" + Thread.currentThread().getId() + "】消費了一個, 還有" + container.getSize() + "個");                }            }        }        if (!container.isFull()) {            synchronized (producerMonitor) {                if (!container.isFull()) {                    producerMonitor.notify();                }            }        }    }}

Container.java

package com.tuhooo.practice.pcmodel;import java.util.LinkedList;import java.util.List;/** * 容器 */public class Container<T> {    private int capacity;    private List<T> list;    public Container(int capacity) {        this.capacity = capacity;        list = new LinkedList<T>();    }    /*往容器中添加*/    public synchronized boolean add(T product) {        if(list.size() < capacity) {            list.add(product);            return true;        }        return false;    }    /*從容器中取*/    public synchronized T get() {        if(list.size() > 0) {            list.remove(0);        }        return null;    }    /*判斷是否是滿的*/    public boolean isFull() {        return list.size() >= capacity;    }    public boolean isEmpty() {        return list.size() == 0;    }    public synchronized int getSize() {        return list.size();    }    public int getCapacity() {        return this.capacity;    }}

Container有點坑的地方就是不知道什麼時候應該加synchronized

 

Test.java

package com.tuhooo.practice.pcmodel;public class Test {    public static void main(String[] args) {        Container<Integer> container = new Container<Integer>(10);        Object producerMonitor = new Object();        Object consumerMonitor = new Object();                Thread p1 = new Thread(new Producer(container, producerMonitor, consumerMonitor));        Thread p2 = new Thread(new Producer(container, producerMonitor, consumerMonitor));        Thread c1 = new Thread(new Consumer(container, producerMonitor, consumerMonitor));        Thread c2 = new Thread(new Consumer(container, producerMonitor, consumerMonitor));        p1.start();        p2.start();        c1.start();        c2.start();    }}

 

目前先就這麼寫,暫時運行起來沒啥問題,如果有問題懇請各位看官指出。

 

有待改進地方:

1. Container有沒有更好的實現方法

2. Container可以有多個,這樣的話可以隨機找到一個可用的Container分配給Producer或者Consumer用

3. 感覺代碼中有好多的synchronized,感覺效能不是很好

生產者和消費者問題學習以及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.