问题描述:
生产者消费者问题(Producer-consumer problem)是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。
如何模拟这个问题?
为了模拟这个问题,我们假设有一个篮子,这个篮子用于装刚刚生产出来的面包,这个篮子能够容纳的面包个数是固定的,所以,如果生产者(面包师傅)发现篮子已经满了,那么就返回厨房等待,当消费者拿掉了一个面包后,消费者会通知厨房的面包师傅,这个篮子已经不是满的了,可以再往里面加面包了。
同理,如果消费者发现篮子里没有面包了,那么他也只能在厅堂等着,当面包师傅往篮子里加了面包以后,面包师傅会通知那些在厅堂里等候拿面包的人,篮子里面已经有面包了。
Bread类用于模拟面包
public class Bread {
int id;
public Bread(int id) {
this.id = id;
}
public String toString() {
return "Bread: " + id;
}
}
public class BreadBucket {
int index = 0;
Bread[] container;
public BreadBucket(int size) {
container = new Bread[size];
}
public synchronized void putBread(Bread bread) {
while (index == container.length) {
try {
this.wait(); // The bucket is full, and the producer needs to wait
} catch (InterruptedException e) {
e.printStackTrace();
}
}
container[index] = bread;
index++;
System.out.println("+++++++New bread added: " + bread);
System.out.println("+++++++Current # of bread in the bucket:" + index);
this.notify(); // notify consumer, the bucket is not empty.
}
public synchronized void takeBread() {
while (index == 0) {
try {
this.wait(); // The consumer needs to wait because the bucket is empty.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
index--;
Bread bread = container[index];
System.out.println("-------Consumed bread: " + bread);
System.out.println("-------Current # of bread in the bucket:" + index);
this.notify(); // notify producer, the bucket is not full
}
}
public class Consumer implements Runnable {
BreadBucket container;
public Consumer(BreadBucket container) {
this.container = container;
}
@Override
public void run() {
while (true) {
container.takeBread();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Producer implements Runnable {
BreadBucket container;
int id = 1;
public Producer(BreadBucket container) {
this.container = container;
}
@Override
public void run() {
while (true) {
Bread bread = new Bread(id++);
container.putBread(bread);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Test {
public static void main(String[] args) {
BreadBucket container = new BreadBucket(10);
Producer p = new Producer(container);
Consumer c = new Consumer(container);
new Thread(p).start();
new Thread(c).start();
}
}
转载请注明出处:blog.youkuaiyun.com/beiyetengqing。