代码仍有不足,仅供参考,本文章不会深入描述生产者消费者的原理,重在如何用Java实现。
目录
一、生产者消费者问题简介
生产者消费者问题 [1](英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区已经装满时加入数据,消费者也不会在缓冲区为空时消耗数据。
二、模拟一个生产者,一个消费者,共享一个缓冲区的情形。
生产者:
class Producer extends Thread {
private Buffer buffer;
public Producer(Buffer buffer) {
this.buffer = buffer;
}
public void run() {
for (int i = 0; i < 10; i++) {
try {
buffer.add(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("produce " + i);
try {
Random random = new Random();
int min = 1000;
int max = 4000;
int randomNumber = random.nextInt(max - min + 1) + min;
Thread.sleep(randomNumber);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
消费者:
class Consumer extends Thread {
private Buffer buffer;
public Consumer(Buffer buffer) {
this.buffer = buffer;
}
public void run() {
for (int i = 0; i < 10; i++) {
int val = 0;
try {
val = buffer.pull();
Random random = new Random();
int min = 4000;
int max = 10000;
int randomNumber = random.nextInt(max - min + 1) + min;
Thread.sleep(randomNumber);
System.out.println("consume" + val);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
缓冲区:
class Buffer {
private Queue<Integer> queue = new LinkedList<>();
private int size = 5;
public synchronized void add(int val) throws InterruptedException {
while (queue.size() >= size) {
wait();
System.out.println("buffer is full please consume");
}
queue.add(val);
notify();
}
public synchronized int pull() throws InterruptedException {
while (queue.size() == 0) {
wait();
System.out.println("buffer is empty");
}
int val = queue.poll();
notify();
return val;
}
}
实现效果展示:
三、模拟多个生产者,多个消费者,共享多个缓冲区的情形
生产者:
class Producer extends Thread {
private Buffer buffer;
private int id;
public Producer(Buffer buffer, int id) {
this.buffer = buffer;
this.id = id;
}
public void run() {
for (int i = 0; i < 5; i++) {
try {
buffer.add(i, id);
System.out.println("Producer " + id + " produced: " + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Random random = new Random();
int min = 1000;
int max = 4000;
int randomNumber = random.nextInt(max - min + 1) + min;
Thread.sleep(randomNumber);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
消费者:
class Consumer extends Thread {
private Buffer buffer;
private int id;
public Consumer(Buffer buffer, int id) {
this.buffer = buffer;
this.id = id;
}
public void run() {
for (int i = 0; i < 5; i++) {
try {
int[] val = buffer.pull(id);
System.out.println("Consumer " + id + " consumed: " + val[0] + " (Produced by Producer " + val[1] + ")");
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Random random = new Random();
int min = 4000;
int max = 10000;
int randomNumber = random.nextInt(max - min + 1) + min;
Thread.sleep(randomNumber);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
缓冲区:
class Buffer {
private Queue<Integer[]> queue = new LinkedList<>();
private int size = 5;
private int lastProducerId = -1;
public synchronized void add(int val, int producerId) throws InterruptedException {
while (queue.size() >= size || producerId == lastProducerId) {
wait();
System.out.println("Buffer is full or same producer. Please consume or change producer.");
}
Integer[] item = {val, producerId};
queue.add(item);
lastProducerId = producerId;
notifyAll();
}
public synchronized int[] pull(int consumerId) throws InterruptedException {
while (queue.size() == 0) {
wait();
System.out.println("Buffer is empty.");
}
Integer[] item = queue.poll();
notifyAll();
return new int[]{item[0], item[1]};
}
}
主函数:
public static void main(String[] args) {
Buffer buffer = new Buffer();
// 创建多个生产者多个消费者
for (int i = 0; i < 3; i++) {
Producer producer = new Producer(buffer, i);
Consumer consumer = new Consumer(buffer, i);
producer.start();
consumer.start();
}
}
}
效果展示: