生产者与消费者问题问题是线程同步里边一个很经典的问题。
用通俗的语言来描述这个过程:
一群生产者不断的生产产品,并将产品放到一个容器里边;同时一群消费者不断从容器里边消费产品。
容器的容量是有限的。如果容器满了,生产者不能再往容器放产品,必须进入等待状态。等待产品被消费者拿走了,再往容器放产品。
同样,如果容器空了,消费者也必须进入等待状态。等待生产者往里边放产品,再将消费者唤醒。
java实现需要四个类:一个生产者,一个消费者,一个容器类,一个产品类。
这里以生产者生产面包为例
具体实现如下:
Bread.java (面包类,具体的产品实体)
public class Bread {
private int id; //面包ID
private int productId;//生产者ID
public Bread(){
}
public Bread(int id,int productId){
this.id = id;
this.productId = productId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
}
Basket.java(篮子,盛放面包的容器)
public class Basket {
private Bread []breads = new Bread[10]; //存储生产的面包
private int index = 0;//标记当前可用数组空间下标
public synchronized void push(Bread b){
System.out.println("生产者等待放入面包。。。。");
while(index == breads.length){
try{
this.wait(); //如果篮子已满,使当前生产者线程等待
}catch(InterruptedException ie){
ie.printStackTrace();
}
}
this.notify(); //唤醒一个生产者线程
breads[index++] = b;
System.out.println("生产者"+b.getProductId()+"生产了一个面包"+index);
}
public synchronized void pop(int cid){
System.err.println("消费者"+cid+"等待消费面包。。。。");
while(index==0){
try{
this.wait();
}catch(InterruptedException ie){
ie.printStackTrace();
}
}
this.notify();
System.out.println(index+"面包被顾客"+cid+"消费!");
index--;
}
}
Producer.java(生产者,生产面包,继承了Thread类)
public class Producer extends Thread{
private int id;
private Basket basket;
public Producer(int id,Basket basket){
this.id = id;
this.basket = basket;
}
@Override
public void run(){
for(int i=0;i<10;i++){
Bread b = new Bread(i,id);
basket.push(b);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Customer.java(消费者,消费面包,继承了Thread类)
public class Customer extends Thread{
private int id; //消费者Id
private Basket basket;//消费对应的篮子的引用
public Customer(int id,Basket basket){
this.id = id;
this.basket = basket;
}
@Override
public void run() {
for(int i=0;i<10;i++){
basket.pop(id);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class Test {
public static void main(String[] args) {
Basket b = new Basket(); //创建一个篮子实例
Producer p1 = new Producer(1, b);
Producer p2 = new Producer(2, b);
Customer c1 = new Customer(1, b);
Customer c2 = new Customer(2, b);
p1.start();
p2.start();
c1.start();
c2.start();
}
}
运行结果:
生产者等待放入面包。。。。 生产者1生产了一个面包1 1面包被顾客1消费! 消费者1等待消费面包。。。。 消费者2等待消费面包。。。。 生产者等待放入面包。。。。 生产者2生产了一个面包1 1面包被顾客2消费! 生产者等待放入面包。。。。 生产者1生产了一个面包1 消费者1等待消费面包。。。。 1面包被顾客1消费! 生产者等待放入面包。。。。 生产者2生产了一个面包1 生产者等待放入面包。。。。 生产者1生产了一个面包2 消费者1等待消费面包。。。。 2面包被顾客1消费! 消费者2等待消费面包。。。。 1面包被顾客2消费! 生产者等待放入面包。。。。 生产者1生产了一个面包1 |