/**
* 参考资料:https://blog.csdn.net/SheIsSDEatNYC/article/details/108571729
* 生产者-消费者模型,主要实现两者之间的解耦、异步和平衡速度差异。
* 如果队列里的产品已经满了,生产者就不能继续生产;
* 如果队列里的产品从无到有,生产者就得通知一下消费者,告诉它可以来消费了;
* 如果队列里已经没有产品了,消费者也无法继续消费;
* 如果队列里的产品从满到不满,消费者也得去通知下生产者,说你可以来生产了。
* 它们之间的协作,就是使用Object类里自带的wait()和notify()或者notifyAll()的消息通知机制。
* wait()方法是用来让当前线程等待,直到有别的线程调用notify()将它唤醒,或者我们可以设定一个时间让它自动苏醒。
* 调用notify方法之前,线程必须要获得该对象的对象监视器锁,也就是只能用在加锁的方法下。而调用该方法之后,当前线程会释放锁。
* notify()方法只能通知一个线程,如果多个线程在等待,那就唤醒任意一个。
* notifyAll()方法是可以唤醒所有等待线程,然后加入同步队列。
*/
public class ProducerAndConsumerDemo {
public static void main(String[] args){
Queue<Product> queue = new ArrayDeque<>();
for(int i=0;i<100;i++){
new ProducerThread(queue,100).start();
new ConsumerThread(queue,100).start();
}
}
/**
* 生产者
*/
static class ProducerThread extends Thread{
private Queue<Product> queue;
private int maxCapacity;
public ProducerThread(Queue<Product> queue,int maxCapacity){
this.queue = queue;
this.maxCapacity = maxCapacity;
}
@Override
public void run(){
/**
* 生产者线程拿到锁后,其实就是进入了运行中阶段。
* 首先检查队列是否容量已满,如果满了,那就要去等待;
* 如果不满,先检查一下队列原本是否为空,如果原来是空的,那就需要通知消费者;最后生产产品。
*/
synchronized (queue){
// 如果没有地方暂存商品,则进入等待
while(queue.size()==maxCapacity){
System.out.println("当前生产者"+Thread.currentThread().getName()+"生产商品无法暂存,将进入等待中");
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 如果暂存的商品为0,则开始生产的时候,需要通知在等待的消费线程
if(queue.isEmpty()){
queue.notifyAll();
}
Product product = new Product(String.valueOf(new Random().nextInt()));
queue.offer(product);
System.out.println("当前生产者"+Thread.currentThread().getName()+"生产商品"+product.name);
}
}
}
/**
* 消费者
*/
static class ConsumerThread extends Thread{
private Queue<Product> queue;
private int maxCapacity;
public ConsumerThread(Queue<Product> queue,int maxCapacity){
this.queue = queue;
this.maxCapacity = maxCapacity;
}
@Override
public void run(){
synchronized (queue){
// 如果没有商品可消费,则进入等待
while(queue.isEmpty()){
System.out.println("当前消费者"+Thread.currentThread().getName()+"无商品可消费,将进入等待");
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("当前消费者"+Thread.currentThread().getName()+"无商品可消费等待结束");
}
// 如果暂存的商品以满,则开始消费的时候,需要通知在等待的生产线程
if(queue.size()==maxCapacity){
queue.notifyAll();
}
System.out.println("当前消费者"+Thread.currentThread().getName()+"消费商品"+queue.poll().name);
}
}
}
static class Product{
/**
* 商品的名称
*/
private String name;
public Product(String name){
this.name = name;
}
}
}