经典生产者消费者问题
2017-11-16 本文已影响7人
孙浩j
需求分析:假设生产者生产馒头,有一个容器只能装10个馒头,
1.当容器里没有馒头时,消费者不能消费(消费者的线程进入等待),当生产者生产一个馒头就叫醒了这个等待消耗的消费者线程。
2.当容器馒头超过10个,生产者不能生产(生产者的线程进入等待),当消费者消耗了一个以后,就叫醒了等待的生产者线程,生产者可以生产。
3.生产一个馒头就把馒头放到容器里,消费一个馒头就把馒头从容器里删除
4.生产,消费不能同时进行,加锁
类:馒头类,容器类,生产者类,消费者类
资源类:
public class ManTou {
int id;
public ManTou (int id){
this.id=id;
}
public int getId(){
return id;
}
@Override
public String toString() {
return "ManTou [id=" + id + "]";
}
}
容器类
import java.util.List;
import java.util.LinkedList;
public class LanZi {
ManTou [] m=new ManTou[10]; //放馒头 //建立数组用于放馒头
int index=0; //放馒头的位置
public synchronized void push(ManTou mt) throws InterruptedException{ //生产馒头
if(index==m.length){ //篮子装的额馒头数量等于容量时,线程挂起
wait();//这个地方不用if else 原因是
}else{
m[index]=mt; //生产馒头
System.out.println(m[index].id+"号馒头生产完成");
for(int i=0;i<m.length;i++){
if(m[i]!=null){
System.out.println("篮子里有"+(m[i])+"馒头");//显示容器里的馒头
}
}
notify(); //用于叫醒当没有馒头时,等待的消费者
index++; //放馒头的位置+1
Thread.sleep(1000);
}
}
public synchronized void pop() throws InterruptedException{ //拿馒头
if(index==0){ //当没有馒头,线程挂起等待
wait();
}else{ //消费馒头
index--; //由于生产完,放馒头的地方就加了,所以消耗就要消耗前一个位置的馒头
System.out.println("吃了"+m[index].id+"号馒头");
m[index]=null; //吃完之后容器里就没有这个馒头了
notify(); //用于叫醒馒头满了而停下的生产者
Thread.sleep(1000);
}
}
}
生产者类
public class Produce implements Runnable {
LanZi l=null;
public Produce(LanZi l){ //确保生产者消费者使用的是同一个篮子
this.l=l;
}
@Override
public void run() {
// TODO Auto-generated method stub
int i=0;
ManTou m=null;
while(true){
boolean b=true;
for(int j=0;j<l.m.length;j++){
if(l.m[j]==null){ //找到数组里没放馒头的位置
b=false;
break; //没有位置放的话就不要生产了
}
}
if(!b){
//如果为空可以生产馒头
m=new ManTou(++i); //新馒头
}
try {
l.push(m); //将生产的馒头放入数组
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
消费者类
public class Consume implements Runnable{
LanZi l=null;
public Consume(LanZi l){
this.l=l;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
l.pop();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Thread.sleep(60);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}