1. 程式人生 > 其它 >生產者消費者模型--管程法

生產者消費者模型--管程法

理解:

生產者將生產好的資料放入緩衝區 , 消費者從緩衝區拿出資料。通過判斷緩衝區大小來決定生產者何時生產,消費者何時消費。只要緩衝區有產品,消費者就可以消費。只要緩衝區不滿,生產者就可以生產。

模型:

  • 生產者 : 負責生產資料的模組 (可能是方法 , 物件 , 執行緒 , 程序) ;

  • 消費者 : 負責處理資料的模組 (可能是方法 , 物件 , 執行緒 , 程序) ;

  • 緩衝區 : 消費者不能直接使用生產者的資料 , 而是通過緩衝區拿出資料。

    1)wait()、notify()和notifyAll()方法是本地方法,並且為final方法,無法被重寫。

  2)呼叫某個物件的wait()方法能讓當前執行緒阻塞,並且當前執行緒必須擁有此物件的monitor(即鎖,或者叫管程)

  3)呼叫某個物件的notify()方法能夠喚醒一個正在等待此物件的monitor的執行緒,如有多個執行緒都在等此物件的monitor,則只能喚醒其中一個執行緒;

  4)呼叫notifyAll()方法能夠喚醒所有正在等待這個物件的monitor的執行緒;

———————————————————————————————————————————————————

package com.kaka.thread;

//測試生產者消費者模型--->利用緩衝區解決:管程法


import java.awt.*;

//生產者、消費者、產品、緩衝區
public class TestPC {
    public static void main(String[] args) {

        SynContainer container=new SynContainer();

        new Product(container).start();
        new Customer(container).start();
    }
}

//生產者
class Product extends Thread{
    SynContainer container;
    public Product(SynContainer container){
        this.container=container;
    }

    //生產過程
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            container.push(new Chicken(i));

        }
    }
}

//消費者
class Customer extends Thread{
    SynContainer container;
    public Customer(SynContainer container){
        this.container=container;
    }

    //消費過程
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            container.pop();

        }
    }

}

//產品
class Chicken{
    int id;
    Chicken(int id){
        this.id=id;
    }
}

//緩衝區
class SynContainer{

    //容器大小
    Chicken[] chickens=new Chicken[10];
    //容器計數器
    int count=0;

    //生產者-->放入產品
    public synchronized void push(Chicken chicken){

        //如果容器滿了,就需要等待消費者消費
        if(count==chickens.length){
            //生產等待
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //如果沒有滿就需要丟入產品
        chickens[count]=chicken;
        count++;
        System.out.println("生產了第"+count+"只雞");

        //可以通知消費者消費了
        this.notifyAll();
    }

    //消費者-->消費產品
    public synchronized void pop(){
            //判斷能否消費
            if(count==0){
            //消費等待
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //如果有產品就要消費

            //Chicken chicken=chickens[count];//注意此處陣列下標與個數的區別,兩者相差1,因此要count--再作為下標
            System.out.println("消費了第"+count--+"只雞");

            //吃完了通知消費者生產
            this.notifyAll();


            }


    }