关于生产者与消费者的问题,百度百科上的定义是这样的:生产者消费者问题,也称有限缓冲问题,是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
今天在学习java时遇到这个问题,以一个具体的例子来看这个问题:有生产者生产馒头,消费者在吃馒头,一个放馒头的篮子,生产者和消费者就相当于两个线程,篮子相当于缓冲区;用java模拟这个问题,需要定义两个线程类Producer和Consumer,以及一个栈的类SyncStack,栈相当于篮子;生产者做好馒头放进篮子里,消费者从篮子里面拿馒头,具体代码如下:
public class ProducerConsumer {
/**
* @param args
* 主函数,测试代码
* 一个生产者,一个消费者,栈数组容量为6
*/
public static void main(String[] args) {
SyncStack ss=new SyncStack();
Producer p=new Producer(ss);
Consumer c=new Consumer(ss);
new Thread(p).start();
new Thread(c).start();
}
}
class ManTou {
int id;
ManTou(int id) {
this.id=id;//生产的每个馒头给一个id
}
public String toString() {
return "Mantou:"+id;
}
}
/*定义一个栈模拟缓冲区*/
class SyncStack {
int index=0;//栈中剩余元素个数,地址值
ManTou[] arrMT=new ManTou[6];//馒头类型的数组,容量为6
/**
* @param mt
* push定义为synchronized类型的,避免mt的产生和地址的增加不同步
*/
public synchronized void push(ManTou mt) {
while(index==arrMT.length) {//当栈满时,进入wait等待
try {
this.wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
this.notify();//唤醒当前进程
arrMT[index]=mt;
index++;
System.out.println("剩余个数:" +index);
}
/**
* @return arrMT[index]
* pop方法同样为synchronized类型
*/
public synchronized ManTou pop() {
while(index==0) {
try {
this.wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
index--;
System.out.println("剩余个数:" +index);
return arrMT[index];
}
}
//生产者的线程类
class Producer implements Runnable{
SyncStack ss=null;
Producer(SyncStack ss) {
this.ss=ss;
}
public void run() {
for(int i=0;i<10;i++) {
ManTou mt=new ManTou(i);
ss.push(mt);
System.out.println("生产了"+mt);
try {
Thread.sleep(1000);//每生产一次sleep 1 s
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
//消费者的线程类
class Consumer implements Runnable{
SyncStack ss=null;
Consumer(SyncStack ss) {
this.ss=ss;
}
public void run() {
for(int i=0;i<10;i++) {
ManTou mt=new ManTou(i);
ss.pop();
System.out.println("消费了"+mt);
try {
Thread.sleep(3000);//每消费一次sleep 3 s
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果:
生产和消费的个数都是10,当生产满6个时将不再生产(栈满),等到消费者消费后又会生产。