生产者消费者模式是一个非常经典的多线程并发协作的模式
1.什么是生产者消费者问题
答:生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
所谓生产者-消费者问题,实际上主要是包含了两类线程,一种是生产者线程用于生产数据,另一种是消费者线程用于消费数据,为了解耦生产者和消费者的关系,通常会采用共享的数据区域,就像是一个仓库,生产者生产数据之后直接放置在共享数据区中,并不需要关心消费者的行为;而消费者只需要从共享数据区中去获取数据,就不再需要关心生产者的行为。但是,这个共享数据区域中应该具备这样的线程间并发协作的功能:
- 如果共享数据区已满的话,阻塞生产者继续生产数据放置入内;
- 如果共享数据区为空的话,阻塞消费者继续消费数据;
在实现生产者消费者问题时,可以采用三种方式:
1.使用Object的wait、notifyAll的消息通知机制
2.使用Lock的Condition的await、signal的消息通知机制
3.使用BlockingQueue实现
第一种方法:使用Object的wait、notifyAll的消息通知机制
定义缓冲区:
定义生产者消费者:
结果显示:
第二种:使用Lock的Condition的await、signal的消息通知机制
一个lock对象可以有很多个Condition类,Condition类负责对lock对象进行await和signal操作,相当于wait、notify、notifyAll操作
在jdk1.5以后,将同步synchronized替换成了Lock,将同步锁对象换成了Condition对象,并且Condition对象可以有多个,这样可以解决一个问题。
定义库存:
定义生产者消费者:
结果:
第三种方法:使用BlockingQueue实现
BlockingQueue的put和take底层实现其实也是使用了第二种方式中的ReentrantLock+Condition,并且帮我们实现了库存队列,方便简洁。
生产者:
消费者:
库存:
结果: