生产者-消费者模式
简介
- 从字面意思就可以先稍微理解一下这个模式
- 就是
生产者生产多少,消费者就消费多少
消费者消费得太多,那么生产者就应该要多生产一些
- 那么这里就有一个
阈值也就叫缓存区
,就是消费到一个什么样的程度
的时候,生产者就要生产了
网上面大多都是用wait-notify,这样堵塞的方式来举例生产者-消费者模式
- 消费者消费到了阈值,就wait阻塞消费者,notify唤醒生产者去生产
- 生产者生产好了就wait阻塞生产者,再notify唤醒消费者
- 这样来举例子
Java中有一个很明显的生产者-消费者模式
线程池 -> 生产者-消费者模式
- 线程池先定义一个阈值 -> 缓冲区,就是工作队列这个参数
- 我们的
线程就作为消费者,线程池作为生产者
- 线程太多了,达到了超过了这个工作队列定义的这个阈值
- 线程池就需要多创建线程,来满足我们对线程的需求
线程池
- 线程池先创建
10个线程
,定义一个工作队列为5
作为阈值 -> 缓冲区 - 我们要使用的线程等于12的时候,10个线程会正常执行
- 多出来的2个任务,会加入到工作队列中
- 当任务要使用的
线程为16
的时候,工作队列最多放下5个,已经放不下了 - 线程池作为
生产者就需要多创建一个线程
出来,供任务使用
实现
public class 生产者消费者模式 {
public static void main(String[] args) {
Container container = new Container();
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 6; i++) {
if (i < 4) {
executorService.execute(new Producer(container));
}
executorService.execute(new Consumer(container));
}
}
}
//生产者
class Producer implements Runnable {
private Container container;
public Producer(Container container) {
this.container = container;
}
@Override
public void run() {
container.put(new Random().nextInt(100));
}
}
//消费者
class Consumer implements Runnable {
private Container container;
public Consumer(Container container) {
this.container = container;
}
@Override
public void run() {
container.take();
}
}
//容器
class Container {
LinkedList<Integer> list = new LinkedList<Integer>();
int capacity = 10;
//生产
public void put(int value) {
while (true) {
synchronized (this) {
//当容器满的时候,producer处于等待状态
while (list.size() == capacity) {
System.out.println("容器已满,等待....");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//没有满,则继续produce
System.out.println("制作者--" + Thread.currentThread().getName() + "--放:" + value);
list.add(value++);
//唤醒其他所有处于wait()的线程,包括消费者和生产者
notifyAll();
}
}
}
//消费
public Integer take() {
Integer val = 0;
while (true) {
synchronized (this) {
//如果容器中没有数据,consumer处于等待状态
while (list.size() == 0) {
System.out.println("容器是空的,等待 ...");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果有数据,继续consume
val = list.removeFirst();
System.out.println("消费者--" + Thread.currentThread().getName() + "--拿:" + val);
notifyAll();
}
}
}
}