Java implementa el patrón productor-consumidor

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

inserte la descripción de la imagen aquí

Tres: Implementación

  1. Adopte el método de notificación de espera
  2. 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

https://www.jb51.net/article/187908.htm

Supongo que te gusta

Origin blog.csdn.net/m0_50370837/article/details/124327448
Recomendado
Clasificación