在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这种生产消费能力不均衡的问题,便有了生产者和消费者模式。
生产者和消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通信,而是通过阻塞队列来进行通信,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
容器队列
package main.java.com.robot.demo.productAndConsumer;
import java.util.LinkedList;
/**
* @author: 会跳舞的机器人
* @date: 2017/8/11 15:51
* @description: 仓库
*/
public class Storage {
/**
* 仓库最大容量
*/
private final int MAX_SIZE = 100;
/**
* 产品的存放队列
*/
private LinkedList<Object> list = new LinkedList<>();
/**
* 生产产品
*/
public void produce(int num) {
synchronized (list) {
while (list.size() + num > MAX_SIZE) {
System.out.println("当前仓库产品数量为:" + list.size() + ",此次生产产品数量为:" + num + ",超过仓库最大容量:" + MAX_SIZE + ",不能再进行生产。");
// 条件不满足,生产阻塞
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 满足条件,生产num个产品
for (int i = 0; i < num; ++i) {
list.add(new Object());
}
System.out.println("此次生产产品数量为:" + num + ",仓库已用容量:" + list.size());
// 通知
list.notifyAll();
}
}
/**
* 消费产品
*/
public void consume(int num) {
synchronized (list) {
while (list.size() < num) {
System.out.println("此次消费产品数量为:" + num + ",产品库存为:" + list.size() + ",库存不足,暂时不能消费。");
// 条件不满足,消费阻塞
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 满足条件,消费num个产品
for (int i = 0; i < num; ++i) {
list.remove();
}
System.out.println("此次消费产品数量为:" + num + ",产品库存为:" + list.size());
// 通知
list.notifyAll();
}
}
}
生产者
package main.java.com.robot.demo.productAndConsumer;
/**
* @author: 会跳舞的机器人
* @date: 2017/8/11 15:50
* @description: 生产者
*/
public class Producer extends Thread {
private int num;
private Storage storage;
public Producer(int num, Storage storage) {
this.num = num;
this.storage = storage;
}
@Override
public void run() {
storage.produce(num);
}
}
消费者
package main.java.com.robot.demo.productAndConsumer;
/**
* @author: 会跳舞的机器人
* @date: 2017/8/11 15:50
* @description: 消费者
*/
public class Consumer extends Thread {
private int num;
private Storage storage;
public Consumer(int num, Storage storage) {
this.num = num;
this.storage = storage;
}
@Override
public void run() {
storage.consume(num);
}
}
测试
package main.java.com.robot.demo.productAndConsumer;
/**
* @author: 会跳舞的机器人
* @date: 2017/8/11 16:29
* @description:
*/
public class Test {
public static void main(String[] args) {
Storage storage = new Storage();
Producer p1 = new Producer(10, storage);
Producer p2 = new Producer(20, storage);
Producer p3 = new Producer(50, storage);
Producer p4 = new Producer(80, storage);
Consumer c1 = new Consumer(30, storage);
Consumer c2 = new Consumer(10, storage);
Consumer c3 = new Consumer(60, storage);
p1.start();
p2.start();
p3.start();
p4.start();
c1.start();
c2.start();
c3.start();
}
}
测试结果输出:
此次生产产品数量为:10,仓库已用容量:10
此次生产产品数量为:50,仓库已用容量:60
当前仓库产品数量为:60,此次生产产品数量为:80,超过仓库最大容量:100,不能再进行生产。
此次消费产品数量为:30,产品库存为:30
此次生产产品数量为:20,仓库已用容量:50
此次消费产品数量为:10,产品库存为:40
当前仓库产品数量为:40,此次生产产品数量为:80,超过仓库最大容量:100,不能再进行生产。
此次消费产品数量为:60,产品库存为:40,库存不足,暂时不能消费。