线程通信中的生产者与消费者模型
生产者与消费者模型——线程通信
利用缓冲区解决:管程法
生产者与消费者模型中主要包含:生产者、消费者、产品、缓冲区四个部分
顾名思义:
- 生产者负责向缓冲区中投入产品
- 消费者负责向缓冲区中取出产品
- 产品(乖乖做自己就好了)
- 缓冲区是模型中的核心部分
缓冲区中主要有容器,以及向容器中添加或取出产品的方法,方法(加了synchronized锁)中处理数据,并且负责线程之间的通信。
具体流程看代码:
//生产者、消费者、产品、缓冲区
public class TestPC {
public static void main(String[] args) {
//实例化一个容器
SynContainer synContainer = new SynContainer();
//生产者
new Producer(synContainer).start();
//消费者
new Consumer(synContainer).start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("剩余chicken:"+synContainer.count);
}
}
//生产者
class Producer extends Thread{
//获得容器
private SynContainer container;
public Producer(SynContainer container){
this.container=container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
container.push(new Chicken(i));
}
}
}
//消费者
class Consumer extends Thread{
//获得容器
private SynContainer container;
public Consumer(SynContainer container){
this.container=container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
container.pop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//产品
class Chicken{
int id;//产品编号
public Chicken(int id) {
this.id = id;
}
}
//缓冲区
class SynContainer{
//需要定义一个容器大小
Chicken[] chickens=new Chicken[20];
int count=0;//计数器(数组当前下标)
int i=1;//记录生产第几只鸡
int j;//记录消费第几只鸡
//生产者放入产品
public synchronized void push(Chicken chicken){
//如果容器已满,则生产者等待
if (count==chickens.length){
try {
System.out.println("容器已满");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//容器未满则生产
chickens[count]=chicken;
System.out.println("生产了第-->"+(i++)+"只鸡--pc-->"+count);
j=i-1;//给消费第几只鸡赋值(从最后一只开始消费)
count++;
//通知消费者消费
notifyAll();
}
//消费者取出产品
public synchronized Chicken pop() throws InterruptedException {
//如果容器为空则等待
if (count==0){
System.out.println("容器已空");
this.wait();
}
//不为空则消费
count--;//因为在生产时最后将count++。其实count指向当前数组中最后一个元素位置的下一个位置,所以消费时先count--,就指向了最后一个元素
Chicken chicken = chickens[count];
System.out.println("--消费了第-->"+(j--)+"只鸡--cc-->"+count);
//通知生产者生产
notifyAll();
return chicken;
}
}
运行结果:
注意:
- pc表示生产者当前在数组中所投产品的下标位置
- cc表示消费者当前在数组中所取产品的下标位置