package com.example.springboottestone.main;
import java.util.LinkedList;
import java.util.Queue;
/**
* 多生产者多消费者模型是指多个生产者线程同时向缓冲区中添加数据,同时多个消费者线程从缓冲区中获取数据的并发模型。这种模型适用于需要高并发处理数据的场景,能够充分利用多线程的优势,提高系统的处理能力和效率。
* 在多生产者多消费者模型中,需要解决以下几个关键问题:
* 1. 共享缓冲区:多个生产者线程和消费者线程都需要访问同一个缓冲区,因此需要通过同步机制来保证线程之间的安全访问。
* 2. 生产者操作:生产者线程向缓冲区中添加数据,如果缓冲区已满,则需要等待;如果缓冲区有空闲位置,则将数据添加到缓冲区,并唤醒等待中的消费者线程。
* 3. 消费者操作:消费者线程从缓冲区中获取数据,如果缓冲区为空,则需要等待;如果缓冲区有数据,则从缓冲区中获取数据,并唤醒等待中的生产者线程。
* 4. 同步机制:可以使用锁、条件变量等同步机制来实现多生产者多消费者模型。例如,可以使用`ReentrantLock`和`Condition`来控制对缓冲区的访问和线程的等待与唤醒。
* 一个常见的实现方式是使用一个有界队列作为共享缓冲区,生产者线程向队列中添加数据,消费者线程从队列中获取数据。生产者线程和消费者线程通过对队列进行操作来进行线程间的同步和协调。
* 在这种模型中,需要注意如下几点:
* - 避免队列溢出和队列为空的情况,以避免生产者和消费者线程陷入等待状态。
* - 在实现中,需要正确处理线程的等待和唤醒操作,以确保生产者和消费者线程能够正确地等待和唤醒。
* - 需要考虑线程安全的问题,使用适当的同步机制来保证对共享资源的安全访问。
* - 对于大规模的多生产者多消费者模型,还可以考虑使用线程池来管理线程的创建和销毁,以减少线程的创建和销毁的开销。
* 总的来说,多生产者多消费者模型是一种常见的并发处理模型,通过合理设计和实现,能够有效地提高系统的处理能力和效率。
*/
public class ProducerConsumer {
private static final int BUFFER_SIZE = 10;
private static Queue<Integer> buffer = new LinkedList<>();
public static void main(String[] args) {
// 创建生产者和消费者线程
Thread producer1 = new Thread(new Producer(), "Producer 1");
Thread producer2 = new Thread(new Producer(), "Producer 2");
Thread consumer1 = new Thread(new Consumer(), "Consumer 1");
Thread consumer2 = new Thread(new Consumer(), "Consumer 2");
// 启动线程
producer1.start();
producer2.start();
consumer1.start();
consumer2.start();
}
static class Producer implements Runnable {
@Override
public void run() {
try {
while (true) {
synchronized (buffer) {
// 如果缓冲区已满,则等待
while (buffer.size() == BUFFER_SIZE) {
buffer.wait();
}
// 生成一个物品并将其添加到缓冲区
int item = (int) (Math.random() * 100);
buffer.add(item);
System.out.println(Thread.currentThread().getName() + " 生成物品:" + item);
// 通知消费者有物品可用
buffer.notifyAll();
}
// 在生成下一个物品之前,休眠一段时间
Thread.sleep((int) (Math.random() * 1000));
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
static class Consumer implements Runnable {
@Override
public void run() {
try {
while (true) {
synchronized (buffer) {
// 如果缓冲区为空,则等待
while (buffer.isEmpty()) {
buffer.wait();
}
// 从缓冲区中消费一个物品
int item = buffer.poll();
System.out.println(Thread.currentThread().getName() + " 消费物品:" + item);
// 通知生产者缓冲区有空位
buffer.notifyAll();
}
// 在消费下一个物品之前,休眠一段时间
Thread.sleep((int) (Math.random() * 1000));
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}