Java中的生产者消费者模型属于编程中的经典模型,下面利用线程简单模拟一下这个模型,例子:两个生产者生产馍馍(馒头),往装馍馍的篮子里面放,篮子用数组模拟栈先进后出且大小为10,当生产者把篮子装满了即刻等着同时通知消费者消费;当消费者把篮子消费空了即刻等着同时通知生产者生产。
代码并不复杂,使用线程同步关键字synchronized即可完成……
Coding:
/**
* 利用传统线程实现生产者消费者模型
*
* 利用两根线程生产20个馍馍,一根线程消费20个馍馍,协调作业,
*
* <li>一根线程 wait 则需要调用 notify 方法 </li>
* <li>多根线程 wait 则需要调用 notifyAll 方法</li>
*
* 注意:
* <li>wait 方法在等待的同时会释放对象锁,让其它的线程有机会获取对象锁</li>
* <li>sleep 方法在休眠的时候不会释放对象锁,其它的线程无法获取对象锁</li>
*
* @author 吖大哥
* @date Jun 2, 2014 2:13:01 PM
*/
public class ProducerConsumer {
public static void main(String[] args) {
BasketStack bs = new BasketStack();
Producer p = new Producer(bs);
Consumer c = new Consumer(bs);
// 生产者生产20个馍馍
new Thread(p).start();
new Thread(p).start();
// 消费者消费20个馍馍
new Thread(c).start();
}
}
// 馍馍(馒头)
class MoMo {
private int id;// 馍馍编号
public MoMo(int id) {
this.id = id;
}
@Override
public String toString() {
return "===momo id===" + id;
}
}
// 装馍馍的篮子
class BasketStack {
private int index;
// 可以装馍馍的数组
private MoMo[] momoArr = new MoMo[10];
// 向篮子里面放馍馍
public synchronized void push(MoMo momo) {
// if (index == momoArr.length) {
// 利用while可以起到双重保险,如果this.wait()出现异常被打断,循环依然可以进行一次判断保证程序不往下执行
while (index == momoArr.length) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
momoArr[index] = momo;
index++;
this.notifyAll();// 通知消费者来消费
}
// 从篮子里面取馍馍
public synchronized MoMo pop() {
// if (index == 0) {
// 利用while可以起到双重保险,如果this.wait()出现异常被打断,循环依然可以进行一次判断保证程序不往下执行
while (index == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();// 通知生产者来生产
index--;
return momoArr[index];
}
}
// 生产者线程
class Producer implements Runnable {
private BasketStack bs = new BasketStack();// 装馍馍的篮子
public Producer(BasketStack bs) {
this.bs = bs;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
MoMo moMo = new MoMo(i);
System.out.println("生产了 " + moMo);
bs.push(moMo);
try {
Thread.sleep((int) (Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
private BasketStack bs = new BasketStack();// 取馍馍的篮子
public Consumer(BasketStack bs) {
this.bs = bs;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
MoMo moMo = bs.pop();
System.out.println("消费了 " + moMo);
try {
Thread.sleep((int) (Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}