生产者消费者模式的实现方式有很多种,比如采用Condition条件变量或者利用阻塞队列来进行实现。本文将采用Object中自带的wait和notify/notifyAll方法来实现这个模式。实现代码如下:
import java.util.LinkedList;
public class ProducerConsumerPattern{
public static final int MAX_CAPACITY = 5; //缓冲区最大容量
static LinkedList<Object> list = new LinkedList<Object>(); //用一个Linked作为缓冲区
static class Producer implements Runnable { //生产者
public void run() {
while(true) { //循环生产产品
synchronized(list) { //获取缓冲区的锁
while(list.size()==MAX_CAPACITY) { // 如果缓冲区已满,
try {
System.out.println("当前产品个数为" + list.size() + "已达到最大容量,等待消费者消费。。。");
list.wait(); //则调用wait进行阻塞,并释放缓冲区的锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("当前产品个数为" + list.size());
list.add(new Object()); //缓冲区未满,则生产产品
System.out.println("生产了一个产品,当前产品个数为" + list.size());
list.notifyAll(); //生产完一个产品之后,通知所有阻塞在wait调用中的线程
}
try {
Thread.sleep(1000); //模拟花费一段时间进行生产
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class Consumer implements Runnable { //消费者
public void run() {
while(true) { //不断消费产品
synchronized(list) { //获取缓冲区的锁
while(list.size()==0) { //如果缓冲区为空,
try {
System.out.println("当前产品个数为" + list.size() + ",等待生产者生产。。。");
list.wait(); //则进行阻塞,并释放缓冲区的锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("当前产品个数为" + list.size());
list.remove(); //缓冲区不空,则消费一个产品
System.out.println("消费了一个产品,当前产品个数为" + list.size());
list.notifyAll(); //消费一个产品之后,通知所有阻塞在wait调用上的线程
}
try {
Thread.sleep(2000); //模拟花费一段时间进行消费
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
for(int i=0; i<3; i++) { //创建3个生产者进行生产
new Thread(new Producer()).start();
}
for(int i=0; i<5; i++) { //创建5个消费者进行消费
new Thread(new Consumer()).start();
}
}
}
某一次的运行结果如下:
当前产品个数为0
生产了一个产品,当前产品个数为1
当前产品个数为1
生产了一个产品,当前产品个数为2
当前产品个数为2
生产了一个产品,当前产品个数为3
当前产品个数为3
消费了一个产品,当前产品个数为2
当前产品个数为2
消费了一个产品,当前产品个数为1
当前产品个数为1
消费了一个产品,当前产品个数为0
当前产品个数为0,等待生产者生产。。。
当前产品个数为0,等待生产者生产。。。
当前产品个数为0
生产了一个产品,当前产品个数为1
………………(省略部分过程)
当前产品个数为3
生产了一个产品,当前产品个数为4
当前产品个数为4
生产了一个产品,当前产品个数为5
当前产品个数为5已达到最大容量,等待消费者消费。。。
当前产品个数为5
消费了一个产品,当前产品个数为4
总结:在实现这个模式的过程中也遇到了一些问题,通过解决遇到的这些问题使自己对java多线程的机制也有了更进一步的了解。有些东西以为自己会,其实并不真的会,还是要多实践。
水平有限,如有不当之处,还望指正!