一个比较经典的问题:生产者/消费者问题,这个问题的解决就是通过灵活使用wait()、notifyALL()方法实现的。
问题描述:
生产者将产品交给店员,而消费者从店员处取走产品,店员一次只能持有固定数量的产品,如果生产者生产了过多的产品,店员就会叫生产者等一下,如果店中有空位放产品了再通知消费者来取走产品。这里可能出现的问题有一下两个:
1、生产者比消费者快时,消费者会漏掉一些数据没有取到
2、消费者比生产者快时,消费者会取相同的数据
一下代码就是解决方案:
//生产者消费者问题
public class ProductTest {
public static void main(String[] args) {
Clerk clerk = new Clerk();
// 生产者线程
Thread producerThread = new Thread(new Producer(clerk));
// 消费者线程
Thread consumerThread = new Thread(new Consumer(clerk));
producerThread.start();
consumerThread.start();
}
}
// 店员
class Clerk {
// 默认为0个产品
private int product = 0;
// 生产者生产出来的产品交给店员
public synchronized void addProduct() {
if (this.product >= 20) {
try {
// 产品已满,请稍候再生产
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
product++;
System.out.println("生产者生产第" + product + "个产品");
// 通知等待区的消费者可以取产品了
notifyAll();
}
}
// 消费者从店员处取产品
public synchronized void getProduct() {
if (this.product <= 0) {
try {
// 缺货,请稍候再取
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("消费者取走了第" + product + "个产品");
product--;
// 通知等待区的生产者可以生产产品了
notifyAll();
}
}
}
class Producer implements Runnable {
private Clerk clerk;
public Producer(Clerk clerk) {
this.clerk = clerk;
}
public void run() {
System.out.println("生产者开始生产产品");
while (true) {
try {
Thread.sleep((int) (Math.random() * 10) * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 生产产品
clerk.addProduct();
}
}
}
class Consumer implements Runnable {
private Clerk clerk;
public Consumer(Clerk clerk) {
this.clerk = clerk;
}
public void run() {
System.out.println("消费者开始取走产品");
while (true) {
try {
Thread.sleep((int) (Math.random() * 10) * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 取产品
clerk.getProduct();
}
}
} |