生產者消費者模型--管程法
阿新 • • 發佈:2021-07-12
理解:
生產者將生產好的資料放入緩衝區 , 消費者從緩衝區拿出資料。通過判斷緩衝區大小來決定生產者何時生產,消費者何時消費。只要緩衝區有產品,消費者就可以消費。只要緩衝區不滿,生產者就可以生產。
模型:
-
生產者 : 負責生產資料的模組 (可能是方法 , 物件 , 執行緒 , 程序) ;
-
消費者 : 負責處理資料的模組 (可能是方法 , 物件 , 執行緒 , 程序) ;
-
緩衝區 : 消費者不能直接使用生產者的資料 , 而是通過緩衝區拿出資料。
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(); } }