一、问题描述
生产者消费者问题是一个典型的线程同步问题。生产者生产商品放到容器中,容器有一定的容量(只能顺序放,先放后拿),消费者消费商品,当容器满了后,生产者等待,当容器为空时,消费者等待。当生产者将商品放入容器后,通知消费者;当消费者拿走商品后,通知生产者。
对容器资源加锁,当取得锁后,才能对互斥资源进行操作。
生产者、消费者是多线程领域具有代表性的业务场景,通过以下代码简单实现了下此业务场景,
主要包含三个组件,
- 生产目标对象,这里以商品为说明,目标对象Goods.
- 目标对象的生产者。
- 目标对象的消费者
- 目标对象的存放容器,这里采用栈的方式,先进后出。
**核心技术点: ** 理解多线程wait、notifyAll的用法
public class ProducerConsumerTest {
public static void main(String[] args) {
Container con = new Container();
Producer p = new Producer(con);
Consumer c = new Consumer(con);
new Thread(p).start();
new Thread(c).start();
}
}
class Goods {
int id;
public Goods(int id) {
this.id = id;
}
public String toString() {
return "商品信息:" + this.id;
}
}
class Container {// 容器采用栈,先进后出
private int index = 0;
Goods[] goods = new Goods[6];
public synchronized void push(Goods good) {
while (index == goods.length) {// 当容器满了,生产者等待
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
goods[index] = good;
index++;
notifyAll();// 当生产者放入商品后通知消费者
}
public synchronized Goods pop() {
while (index == 0) {// 当容器内没有商品是等待
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
index--;
notifyAll();// 当消费者消费了商品后通知生产者
return goods[index];
}
}
class Producer implements Runnable {
Container con = new Container();
public Producer(Container con) {
this.con = con;
}
public void run() {
for (int i = 0; i < 20; i++) {
Goods good = new Goods(i);
con.push(good);
System.out.println("生产了:" + good);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
Container con = new Container();
public Consumer(Container con) {
this.con = con;
}
public void run() {
for (int i = 0; i < 20; i++) {
Goods good = con.pop();
System.out.println("消费了:" + good);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}