1. Что такое модель производитель/потребитель?
Определенный модуль отвечает за формирование данных, которые обрабатываются другим модулем (модуль здесь является обобщенным и может быть классом, функцией, потоком, процессом и т. д.). Модуль, генерирующий данные, называется производителем, модуль, обрабатывающий данные, называется потребителем. Между производителем и потребителем добавляется буферная зона, которую мы условно называем складом.Производитель отвечает за поступление товара на склад, а потребитель отвечает за прием товара со склада.Это составляет производитель-потребитель модель. .
Структурная схема выглядит следующим образом:
Во-вторых, преимущества модели производителя-потребителя:
1. Развязка:
Благодаря наличию буферов между производителями и потребителями отсутствует прямая зависимость, а степень связанности снижается.
2. Поддержка параллелизма:
Поскольку производитель и потребитель являются двумя независимыми параллельными телами, они соединены буфером в качестве моста.Производителю нужно только закинуть данные в буфер, чтобы продолжить производство следующих данных, а потребителю нужно только начать с Просто взять данные в буфере, чтобы они не блокировались из-за скорости обработки друг друга.
3. Поддержка неравномерной занятости:
У буферов есть еще одно преимущество. Преимущество буфера проявляется, если скорость создания данных бывает быстрой и медленной. Когда данные производятся быстро, у потребителя нет времени на их обработку, а необработанные данные могут временно храниться в буфере. После того, как скорость производства производителя замедлится, потребитель будет медленно избавляться от него.
3. Модель «производитель-потребитель» [то есть «производитель-хранилище-потребитель»] правила, которым следует модель:
1. Производители производят только тогда, когда склад не заполнен, и прекращают производство, когда склад заполнен.
2. Потребители могут потреблять только тогда, когда на складе есть товары, и ждать, когда склад опустеет.
3. Когда потребители обнаруживают, что на складе нет товара для потребления, они уведомляют производителя о производстве.
4. Когда производитель производит потребляемый продукт, он должен уведомить об этом ожидающего потребителя.
4. Пример исходного кода:
1. Склад:
package com.hongri.designpattern.producer_consumer;
import java.util.LinkedList;
/**
* 仓库【即共享数据区域】
*/
public class SyncStack {
LinkedList<Integer> list = new LinkedList<>();
int capacity = 10;
public volatile int index;
/**
* 供生产者调用
*
* @param value
*/
public synchronized void push(String producerName, int value) {
while (list.size() >= capacity) {
try {
System.out.println("仓库已满 ---> 生产者--进入wait状态");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//没有满,则继续produce
System.out.println("生产者--" + producerName + "--生产了:" + value);
list.add(value);
//唤醒其他所有处于wait()的线程,包括消费者和生产者
notifyAll();
}
/**
* 供消费者调用
*
* @return
*/
public synchronized int pop(String consumerName) {
int val = 0;
while (list.size() == 0) {
try {
System.out.println(" 仓库无货 ---> 消费者--进入wait状态");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果有数据,继续consume
val = list.removeFirst();
System.out.println(" 消费者------" + consumerName + "--消费了:" + val);
notifyAll();
return val;
}
}
2. Производитель:
package com.hongri.designpattern.producer_consumer;
import java.util.Random;
/**
* 生产者
*/
public class Producer implements Runnable {
private String name;
private SyncStack stack;
public Producer(String name, SyncStack stack) {
this.name = name;
this.stack = stack;
}
@Override
public void run() {
while (true) {
int value = new Random().nextInt(100);
stack.push(name, value);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
3. Потребители:
package com.hongri.designpattern.producer_consumer;
/**
* 消费者
*/
public class Consumer implements Runnable{
private String name;
private SyncStack stack;
public Consumer(String name, SyncStack stack) {
this.name = name;
this.stack = stack;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(3000);
int val = stack.pop(name);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
4. Звоните:
SyncStack stack = new SyncStack();
Producer producer1 = new Producer("Producer1", stack);
Producer producer2 = new Producer("Producer2", stack);
Producer producer3 = new Producer("Producer3", stack);
Consumer consumer1 = new Consumer("Consumer1", stack);
Consumer consumer2 = new Consumer("Consumer2", stack);
Consumer consumer3 = new Consumer("Consumer3", stack);
new Thread(producer1).start();
new Thread(producer2).start();
new Thread(producer3).start();
new Thread(consumer1).start();
new Thread(consumer2).start();
new Thread(consumer3).start();
Результаты теста:
Ссылка:
Обзор шаблона проектирования Java
Приложение шаблона проектирования производителя-потребителя в пуле потоков