生产者-消费者是一个十分经典的多线程并发协作的模式,所谓生产者-消费者问题,实际上主要是包含了两类线程,一类是生产者线程用于源源不断生产数据,另一类是消费者线程用于消费数据,为了解耦生产者和消费者的关系,通常会采用共享的数据区域,就像是一个仓库,生产者生产数据之后直接放置在共享数据区中,并不需要关心消费者的行为;而消费者只需要从共享数据区中拿数据,不需要关心生产者的行为。生产者唯一关心的就是仓库是否有空余地方,而消费者唯一关系的就是仓库中是否有东西可拿。
废话不说直接上代码(csdn的编辑器特么就像一坨屎一样,代码都没法对齐)
package com.java.test.model;
//仓库类
public class Storehouse {
private int capacity; //容量
private int count = 0; //当前物品数
private String name;
private String[] goods; //商品数组
public Storehouse(String name, int capacity) {
this.name = name;
this.capacity = capacity;
goods = new String[capacity];
System.out.println(this.name+"->初始化仓库...");
}
//添加一个物品
public void add(String name) {
goods[count] = name;
count++;
}
//移除一个物品
public String remove() {
count--;
return goods[count];
}
public int getCount() {
return count;
}
public int getCapacity(){
return capacity;
}
}
package com.java.test.model;
public class Producer {
private String name;
private String[] productType;
private boolean isRun = false;
/**
* @param name
* 生产者名称
* @param productType
* 产品种类
*/
public Producer(String name, String[] productType) {
this.name = name;
this.productType = productType;
}
public void start(Storehouse storehouse) {
isRun = true;
System.out.println(this.name + "->开始生产");
Thread thread = new Thread(() -> {
while (isRun) {
try {
synchronized (storehouse) { // 拿到仓库对象的锁(也可理解为现实中的门钥匙)
if (storehouse.getCapacity() == storehouse.getCount()) {// 如果最大容量等于库存量,则等待消费者消费
storehouse.wait();
} else {
String goodName = getProduct(); // 生产一个产品并且放入仓库中
storehouse.add(goodName);
System.out.println(this.name + "->生产了一个 " + goodName + ", 剩余 " + storehouse.getCount());
storehouse.notifyAll(); // 唤醒所有等待仓库对象的进程
}
}
Thread.sleep(10); // 休息10毫秒
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println(this.name + "->生产结束");
});
thread.start();
}
// 停止生产
public void stop() {
isRun = false;
}
/**
* 模拟随机生产水果
* @return
*/
private String getProduct() throws InterruptedException {
int random = (int) (Math.random() * 10) % productType.length;
Thread.sleep(20);
return productType[random];
}
}
package com.java.test.model;
//消费者类
public class Consumer {
private String name;
private boolean isRun = false;
public Consumer(String name) {
this.name = name;
}
public void start(Storehouse storehouse) {
isRun = true;
System.out.println(this.name + "->开始消费");
Thread thread = new Thread(() -> {
while (isRun) {
try {
synchronized (storehouse) {
if (storehouse.getCount() == 0) { //仓库如果为空,则等待
storehouse.wait();
} else {
String goodName = storehouse.remove();
System.out.println(this.name + "->消费了一个 " + goodName + ", 剩余 " + storehouse.getCount());
storehouse.notifyAll(); //唤醒所有等待仓库对象的进程
}
}
Thread.sleep(25); //休息25毫秒
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println(this.name + "->消费结束");
});
thread.start();
}
//停止消费
public void stop() {
isRun = false;
}
}
package com.java.test;
import com.java.test.model.Consumer;
import com.java.test.model.Producer;
import com.java.test.model.Storehouse;
public class Main {
public static void main(String[] args) {
Consumer consumer1 = new Consumer("消费者1");
Consumer consumer2 = new Consumer("消费者2");
Consumer consumer3 = new Consumer("消费者3");
Consumer consumer4 = new Consumer("消费者4");
Producer producer1 = new Producer("生产者1", new String[]{"苹果","香蕉","甘蔗"});
Producer producer2 = new Producer("生产者2",new String[]{"苹果","香蕉","荔枝","甘蔗"});
Storehouse storehouse = new Storehouse("水果仓库", 50);
//开始运作
producer1.start(storehouse);
consumer1.start(storehouse);
producer2.start(storehouse);
consumer2.start(storehouse);
consumer3.start(storehouse);
consumer4.start(storehouse);
}
}