- 模拟面包店生产消费流程:
- 10个生产者,每个每次生产3个;
- 20个消费者,每个每次消费1个 ;
- 最大库存100
public class BreadShop {
/**
* 面包店库存
*/
private static int COUNT;
/**
* 生产者
*/
public static class Producer implements Runnable{
private String name;
public Producer(String name) {
this.name = name;
}
@Override
public void run() {
//一直生产
try {
while(true){
synchronized (BreadShop.class) {
if (COUNT + 3 > 100) {
//库存已满,进入等待
BreadShop.class.wait();
}else{
COUNT += 3;
System.out.printf("生产者%s生产了3个面包,库存%s\n", name, COUNT);
//此时可以生产了,就通知阻塞线程进入就绪态
BreadShop.class.notifyAll();
//模拟耗时
Thread.sleep(200);
}
}
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 消费者
*/
public static class Consumer implements Runnable{
private String name;
public Consumer(String name) {
this.name = name;
}
@Override
public void run() {
try {
while (true){
synchronized (BreadShop.class){
if (COUNT==0){
//库存已空,无法消费
BreadShop.class.wait();
}else{
//库存未空可以消费
COUNT--;
System.out.printf("消费者%s消费了1个面包,库存%s\n",name,COUNT);
//通知阻塞线程计入就绪态可以消费了
BreadShop.class.notifyAll();
//模拟耗时
Thread.sleep(200);
}
}
//模拟耗时
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//同时启动20个消费者
Thread[] consumers=new Thread[20];
for (int i=0;i<20;i++){
consumers[i]=new Thread(new Consumer(String.valueOf(i)));
}
//同时启动10个生产者
Thread[] producers=new Thread[10];
for (int i=0;i<10;i++){
producers[i]=new Thread(new Producer(String.valueOf(i)));
}
for(Thread t:consumers){
t.start();
}
for (Thread t:producers){
t.start();
}
}
}
- 面包店:
- 5个生产者,每个每次生产3个
- 10个消费者,每个每次消费5个
- 最大库存:100
- 需求:面包师傅每个最多生产10次:
- 消费者不再一直消费,把生产者生产完的面包消费完,就结束
- 信息:面包店每天生产面包的最大数量:面包店每天生产5310=150个面包
- 消费者,把150个面包消费完结束
public class BreadShop {
/**
* 生产者数量
*/
private static int producerNum=5;
/**
* 每次生产个数
*/
private static int onceBreadNum=3;
/**
* 每个生产者生产次数
*/
private static int produceTimes=10;
/**
* 消费者数量
*/
private static int consumerNum=10;
/**
* 每个消费者每次消费个数
*/
private static int onceBuyNum=5;
/**
* 面包店最大库存
*/
private static int COUNT=100;
/**
* 面包店当前库存
*/
private static int currentCOUNT;
/**
* 生产面包总数
*/
private static int breadTotal;
/**
* 生产者
*/
public static class Producer implements Runnable{
private String name;
public Producer(String name) {
this.name = name;
}
@Override
public void run() {
try {
//生产次数有限
for (int i=0;i<produceTimes;i++) {
synchronized (BreadShop.class) {
if (currentCOUNT + onceBreadNum >COUNT) {
//库存已满,进入等待
BreadShop.class.wait();
} else {
currentCOUNT += onceBreadNum;
breadTotal += onceBreadNum;
System.out.printf("生产者:%s,生产了:%s次,库存:%s,生产面包总数:%s\n", name, i+1,currentCOUNT,breadTotal);
//此时可以生产了,就通知阻塞线程进入就绪态
BreadShop.class.notifyAll();
//模拟耗时
Thread.sleep(200);
}
}
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 消费者
*/
public static class Consumer implements Runnable{
private String name;
public Consumer(String name) {
this.name = name;
}
@Override
public void run() {
try {
while (true){
synchronized (BreadShop.class){
//生产面包总数达到最大也停止
if (breadTotal==producerNum*onceBreadNum*produceTimes){
break;
}
if (currentCOUNT-onceBuyNum<0){
//库存已空,无法消费
BreadShop.class.wait();
}else{
//库存未空可以消费
currentCOUNT-=onceBuyNum;
System.out.printf("消费者:%s,消费了:%s个面包,库存%s,\n",name,onceBuyNum,currentCOUNT);
//通知阻塞线程计入就绪态可以消费了
BreadShop.class.notifyAll();
//模拟耗时
Thread.sleep(200);
}
}
//模拟耗时
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//同时启动20个消费者
Thread[] consumers=new Thread[consumerNum];
for (int i=0;i<consumerNum;i++){
consumers[i]=new Thread(new Consumer(String.valueOf(i)));
}
//同时启动10个生产者
Thread[] producers=new Thread[producerNum];
for (int i=0;i<producerNum;i++){
producers[i]=new Thread(new Producer(String.valueOf(i)));
}
for(Thread t:consumers){
t.start();
}
for (Thread t:producers){
t.start();
}
}
}