多个生产者多个消费者
管程法:消费者、生产者、被消费的对象(包子) 、缓冲区(包子铺)
1.被消费的对象(包子)
package com.mutouren.demo.ex2;
/**
* @author wrr
* @date 2021/12/4 0004 14:38
* @description TODO
**/
public class Baozi {
//包子的编号
private int num;
Baozi(int num){
this.num=num;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
2.缓冲区(包子铺)
package com.mutouren.demo.ex2;
/**
* @author wrr
* @date 2021/12/4 0004 14:35
* @description 缓冲区 用来存放包子
**/
public class Hcq {
private Baozi[] baozis = new Baozi[10];
private int count = 0;
private static int sxCount = 0;
/**
* 放包子
**/
public synchronized void pushBaozi(Baozi baozi) {
//如果包子满了 等待消费者消费
while (baozis.length == count) {
//通知消费者消费
try {
System.out.println("生产者等待。。。。。");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("生产者开始放。。。。。");
//如果包子没满 则放包子
baozis[count] = baozi;
count++;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "生产了第 " + baozi.getNum() + " 个包子");
this.notifyAll();
}
/**
* 吃包子
**/
public synchronized void eatBaozi() {
//如果没有包子 等待生产者生产包子
//多个生产者消费者时 要是有while 是为了让线程唤醒后
//先判断条件符不符合
while (count == 0) {
if(sxCount==100){
//这里一定第return而不是break 因为break之后 还是会进行消费 会出现数组越界
//return会直接结束该方法
return;
}
//通知消费者消费
try {
System.out.println(Thread.currentThread().getName()+"等待。。。。");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果有 则进行消费
System.out.println(Thread.currentThread().getName()+"开始吃。。。。");
count--;
Baozi baozi = baozis[count];
// System.out.println("count = " + count);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "消费了第 " + baozi.getNum() + " 个包子");
sxCount++;
this.notifyAll();
}
}
3.消费者
package com.mutouren.demo.ex2;
/**
* @author wrr
* @date 2021/12/4 0004 14:37
* @description 生产者
**/
public class Scz implements Runnable {
//生产者消费者都要从缓冲区拿包子
private Hcq hcq;
Scz(Hcq hcq){
this.hcq=hcq;
}
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
hcq.pushBaozi(new Baozi(i));
}
}
}
4.生产者
package com.mutouren.demo.ex2;
/**
* @author wrr
* @date 2021/12/4 0004 14:37
* @description 消费者
**/
public class Xfz implements Runnable {
private Hcq hcq;
public Xfz(Hcq hcq) {
this.hcq=hcq;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
hcq.eatBaozi();
}
}
}
5.主类
package com.mutouren.demo.ex2;
/**
* @author wrr
* @date 2021/12/4 0004 14:58
* @description TODO
**/
public class Test {
public static void main(String[] args) {
Hcq hcq = new Hcq();
Scz scz = new Scz(hcq);
Xfz xfz = new Xfz(hcq);
new Thread(xfz,"消费者1").start();
new Thread(xfz,"消费者2").start();
new Thread(scz,"生产者1111").start();
new Thread(scz,"生产者222").start();
}
}
总结:
多个生产者多个消费者和一个生产者一个消费者不一样的地方是 是在判断等待的地方
1.if判断要改为while 因为会有消费者和生产者会有多个,所有每次得到锁对象之后就需要重新判断条件是不是还符合程序执行的条件
2.消费者里面要加一个线程停止的判断,因为生产者生产完就会有消费者 而消费完之后不一定会再生产 ,就会导致消费者一直在等待
因此 当消费者消费到一定条件之后 就会停止该方法而不是跳过循环 即使用return而不是break;