有人说这个世界上只有两种人:生产者和消费者。要么你生产某种东西,要么你消 费 某种别人生产的东西。当然,你也可能是既是生产者又是消费者,即在某一产品上你 是生产者,在另一产品上又是消费者。但在某个特定的产品上,一个人只能是生产者或 者消费者,而不能二者同时具有。当然,在一个具体的产品上,你可能既不是生产者又 不是消费者。但对于任何特定的产品,它一定存在至少一个生产者和一个消费者。
那么生产者生产的产品有消费者来处理,但消费者一般不直接从生产者手中获取产品,而是通过一个中间机构,比如商店。生产者把产品往商店一放,消费者到这里来拿。为什么需要这个中间机构呢?这是因为商店的存在使得生产者和消费者能够相对独立地运行,而不必亦步亦趋地跟在另一方后面。因为只要商店货架没满,生产者就可以一直生产产品,它不用等消费者订一件产品做一件产品。而如果没有商店,则生产者无法独立操作,必须拿到消费者订单才能生产。而消费者在每次订货后需要等生产者生产出产品才能进行新的处理和订货。这种你走一步我走一步的生产者消费者的模式效率极为低下。
用计算机来模拟生产者消费者是很简单的事:一个线程表示生产者,一个线程表示消费者,一片内存缓冲区代表我们的商店。生产者只负责生产,消费者只负责消费,而产品的管理全都交给商店完成,这就是面向对象的设计原则:一个类只完成一个特定的功能,各个类相对独立又各有联系,实现代码解耦,逻辑非常清晰。反映到Java代码便是:商店作为共享资源,通过同步的机制管理产品的生产和消费,即对外提供生产产品和消费产品的方法,由生产者线程和消费者线程去调用,即可完成需求,下面给出生产者消费者的Java代码示例:
/*
* 生产者消费者问题
* 分析:
* 1.是否是多线程环境?是,生产者和消费者
* 2.是否有共享数据?有,考虑线程安全
* 3.共享数据是什么?即为产品数量
* 4.是否涉及线程间通信?有,用wait()和notify()机制
*/
public class TestProducerAndConsumer {
public static void main(String[] args) {
Clerk clerk =new Clerk();
Thread t1=new Thread(new Producer(clerk));
Thread t2=new Thread(new Consumer(clerk));
t1.start();
t2.start();
}
}
class Clerk{
private int count;
Object o=new Object();
public void addProduct() throws InterruptedException{
synchronized(o){
while(count>=20){
o.wait();
}
count++;
System.out.println("Producer add:"+count);
o.notify();
}
}
public void useProduct() throws InterruptedException{
synchronized(o){
while(count<=0){
o.wait();
}
count--;
System.out.println("Producer use:"+count);
o.notify();
}
}
}
class Producer implements Runnable{
private Clerk clerk;
public Producer(Clerk clerk) {
this.clerk = clerk;
}
public void run() {
while(true){
try {
clerk.addProduct();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable{
private Clerk clerk;
public Consumer(Clerk clerk) {
this.clerk = clerk;
}
public void run() {
while(true){
try {
clerk.useProduct();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}