1: ¿Qué es el modelo productor-consumidor?
El patrón productor-consumidor resuelve el problema del fuerte acoplamiento entre productores y consumidores a través de un contenedor. Los productores y los consumidores no se comunican directamente entre sí, sino que se comunican a través de colas de bloqueo. Por lo tanto, después de que los productores producen datos, no necesitan esperar a que los consumidores procesen los datos, sino que los arrojan directamente a las colas de bloqueo. Los consumidores no piden a los productores datos, pero tomados directamente de la cola de bloqueo, la cola de bloqueo es equivalente a un búfer, equilibrando las capacidades de procesamiento de productores y consumidores.
En pocas palabras:
el modelo productor-consumidor significa que en un sistema, hay dos roles, uno es productor y el otro es consumidor.La comunicación se realiza a través de un búfer (almacén), y el productor coloca los productos producidos en el Almacén. , de donde los consumidores recogen los productos. Cuando el almacén está lleno, el productor bloquea, y cuando el almacén está vacío, el consumidor bloquea.
Dos: diagrama de relación
Tres: Implementación
- Adopte el método de notificación de espera
- utilizando la cola de bloqueo
3.1 esperar—método de notificación
3.1.1 Ejemplo 1
clase de productor
/**
* 生产者类
* 实现runnable接口
* @author DH
*
*/
public class Producer implements Runnable{
private BufferArea ba;
//通过传入参数的方式是使得对象相同,具有互斥锁的效果。
public Producer(BufferArea ba){
this.ba = ba;
}
@Override
public void run() {
while(true){
setIntervalTime();
ba.set();//生产产品
}
}
//设置时间间隔
public void setIntervalTime(){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
clase de consumidor
/**
* 消费者类
* 实现runnable接口
* @author DH
*
*/
public class Consumer implements Runnable{
private BufferArea ba;
public Consumer(BufferArea ba){
this.ba = ba;
}
@Override
public void run() {
while(true){
setIntervalTime();
ba.get();//消费产品
}
}
//设置时间间隔
public void setIntervalTime(){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
almacén
/**
* 仓库
* 缓冲区
* wait()/notify()
* @author DH
*
*/
public class BufferArea {
private int currNum = 0;//当前仓库的产品数量
private int maxNum = 10;//仓库最大产品容量
public synchronized void set(){
if(currNum<maxNum){
currNum++;
System.out.println(Thread.currentThread().getName()+" 生产了一件产品!当前产品数为:"+currNum);
notifyAll();
}else{//当前产品数大于仓库的最大容量
try {
System.out.println(Thread.currentThread().getName()+" 开始等待!当前仓库已满,产品数为:"+currNum);
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void get(){
if(currNum>0){//仓库中有产品
currNum--;
System.out.println(Thread.currentThread().getName()+" 获得了一件产品!当前产品数为:"+currNum);
notifyAll();
}else{
try {
System.out.println(Thread.currentThread().getName()+" 开始等待!当前仓库为空,产品数为:"+currNum);
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
clase de prueba
/**
* 测试类
* @author DH
*
*/
public class MainCode {
public static void main(String[] args) {
//同一个仓库
BufferArea ba = new BufferArea();
//三个生产者
Producer p1 = new Producer(ba);
Producer p2 = new Producer(ba);
Producer p3 = new Producer(ba);
//三个消费者
Consumer c1 = new Consumer(ba);
Consumer c2 = new Consumer(ba);
Consumer c3 = new Consumer(ba);
//创建线程,并给线程命名
Thread t1 = new Thread(p1,"生产者1");
Thread t2 = new Thread(p2,"生产者2");
Thread t3 = new Thread(p3,"生产者3");
Thread t4 = new Thread(c1,"消费者1");
Thread t5 = new Thread(c2,"消费者2");
Thread t6 = new Thread(c3,"消费者3");
//使线程进入就绪状态
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
}
Al establecer el intervalo de tiempo entre productores y consumidores, puede probar la situación cuando el almacén está lleno y vacío. Cuando el intervalo de tiempo del productor es pequeño, significa que la producción es rápida y el almacén estará lleno. Los resultados de la prueba son los siguientes.
¡El productor 2 produjo un producto! El número actual de productos es: 1
Productor 1 produjo un producto! El número actual de productos es: 2
Productores 3 produjeron un producto! El número actual de productos es: 3
Productores ¡3 produjeron un producto! El número actual de productos es: 4
Productores 1 produjo un producto! El número actual de productos es: 5
Productores 2 produjeron un producto! El número actual de productos es: 6 ¡El
productor 1 produjo un producto! El número actual de productos es: 7
Productores 3 produjeron un producto! El número actual de productos es: 8 ¡El
productor 2 produjo un producto! El número actual de productos es: 9
Productores 3 produjeron un producto! El número actual de productos es: 10
Productores 2 ¡Empieza a esperar! El almacén actual está lleno y la cantidad de productos es: 10
Productores 1 ¡Empiece a esperar! El almacén actual está lleno y la cantidad de productos es: 10
¡El consumidor 1 obtuvo un producto! El número actual de productos es:
9¡El consumidor 2 obtuvo un producto! El número actual de productos es: 8
Cuando el intervalo de tiempo del consumidor es pequeño, significa que el consumo es rápido y el almacén estará vacío. Los resultados de la prueba son los siguientes.
¡El consumidor 2 comienza a esperar! El almacén actual está vacío y la cantidad de productos es: 0 ¡El
productor 3 produjo un producto! El número actual de productos es: 1
Productor 2 produjo un producto! El número actual de productos es: 2
Productores 1 produjo un producto! El número actual de productos es:
3¡El consumidor 2 tiene un producto! El número actual de productos es:
2¡El consumidor 1 obtuvo un producto! El número actual de productos es:
1Consumidor 3 tiene un producto! El número actual de productos es: 0
consumidores 3 ¡empieza a esperar! El almacén actual está vacío y el número de productos es: 0
3.1.2 Ejemplo 2
Producto (Almacén)
package test.exception.producer_consumer_model;
/*
假设为产品为笔
*/
public class Production {
private String type = "";
private String color = "";
private long code = 0; // 产品编号
private boolean isProduced = false; // 是否生产完成 初始状态为未生产状态
private boolean isContinueProduce = true; // 是否停产该产品
public void setContinueProduce(boolean continueProduce) {
isContinueProduce = continueProduce;
}
public void setCode(long code) {
this.code = code;
}
public Production(){
}
public boolean isContinueProduce() {
return isContinueProduce;
}
public void setType(String type) {
this.type = type;
}
public void setColor(String color) {
this.color = color;
}
public void setProduced(boolean produced) {
isProduced = produced;
}
public boolean isProduced() {
return isProduced;
}
@Override
public String toString() {
return color + type + "-" + code;
}
}
productor
package test.exception.producer_consumer_model;
public class Producer implements Runnable {
private final Production pen; // 产品
public Producer(Production pen) {
this.pen = pen;
}
// 生产
public void produce() {
long code = 0;
while (this.pen.isContinueProduce()) {
synchronized (this.pen) {
if (this.pen.isProduced()) {
try {
this.pen.wait(); // 等待消费者消费
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 开始生产
this.pen.setType("铅笔");
this.pen.setColor("蓝色");
this.pen.setCode(code++);
this.pen.setProduced(true);
System.out.println(this.pen + " is produced");
this.pen.notify();
}
}
System.out.println("finish producing");
}
@Override
public void run() {
produce();
}
}
consumidor
package test.exception.producer_consumer_model;
public class Consumer implements Runnable {
private final Production pen;
public Consumer(Production pen) {
this.pen = pen;
}
// 持续消费
public void consumer() {
while (this.pen.isContinueProduce()) {
synchronized (this.pen) {
if (!this.pen.isProduced()) {
try {
this.pen.wait(); // 等待生产者生产
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(this.pen + " is consumed"); // 使用
this.pen.setProduced(false); // 使用完后更新状态
this.pen.notify();
}
}
// 确保停止生产后,能够使用最后生产的一支笔
if (this.pen.isProduced()) {
System.out.println(this.pen + " is consumed");
}
System.out.println("finish using");
}
@Override
public void run() {
consumer();
}
}
clase de prueba
package test.exception.producer_consumer_model;
public class Demo {
public static void main(String[] args) throws InterruptedException {
Production pen = new Production();
Consumer consumer = new Consumer(pen);
Producer producer = new Producer(pen);
new Thread(producer).start(); // 开启生产者线程
new Thread(consumer).start(); // 开启消费者线程
Thread.sleep(10000);
pen.setContinueProduce(false); // 10s后停止生产该类型的笔
}
}
resultado de la operación
3.2 Método de cola de bloqueo
Por razones de espacio, la implementación detallada se puede encontrar en mi blog; https://blog.csdn.net/m0_50370837/article/details/124339524
Artículo de referencia: Modelo de productor-consumidor de Java - Blog de Hi-Man - Blog de CSDN