理解:
生产者将生产好的数据放入缓冲区 , 消费者从缓冲区拿出数据。通过判断缓冲区大小来决定生产者何时生产,消费者何时消费。只要缓冲区有产品,消费者就可以消费。只要缓冲区不满,生产者就可以生产。
模型:
-
生产者 : 负责生产数据的模块 (可能是方法 , 对象 , 线程 , 进程) ;
-
消费者 : 负责处理数据的模块 (可能是方法 , 对象 , 线程 , 进程) ;
-
缓冲区 : 消费者不能直接使用生产者的数据 , 而是通过缓冲区拿出数据。
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();
}
}