该例子所应用场景:一个线程负责生产,多个线程(该例为3个)负责消费;生产者不断的往堆栈中加入数据,消费者不断的从堆栈中取数据。
代码如下:
package com.xs.mail.thread;
import java.util.ArrayList;
import java.util.List;
class Widget {
}
class WidgetMaker extends Thread {
List<Widget> finishedWidgets = new ArrayList<Widget>();
public void run() {
try {
while (true) {
//每1秒钟生产一个Widget
Thread.sleep(1000);// act busy
Widget w1 = new Widget();
// 也就是说需要5秒钟才能新产生一个Widget,这决定了一定要用notify而不是notifyAll
// 因为上面两行代码不是同步的,如果用notifyAll则所有线程都企图冲出wait状态
// 第一个线程得到了锁,并取走了Widget(这个过程的时间小于5秒,新的Widget还没有生成)
// 并且解开了锁,然后第二个线程获得锁(因为用了notifyAll其他线程不再等待notify语句
// ,而是等待finishedWidgets上的锁,一旦锁放开了,他们就会竞争运行),运行
// finishedWidgets.remove(0),但是由于finishedWidgets现在还是空的,
// 于是产生异常
// ***********这就是为什么下面的那一句不能用notifyAll而是要用notify
synchronized (finishedWidgets) {
finishedWidgets.add(w1);
finishedWidgets.notify(); // 这里只能是notify而不能是notifyAll
}
}
} catch (InterruptedException e) {
}
}
public Widget waitForWidget() {
synchronized (finishedWidgets) {
if (finishedWidgets.size() == 0) {
try {
System.out.println("暂停线程:" + Thread.currentThread().getName());
finishedWidgets.wait();
} catch (InterruptedException e) {
}
}
return finishedWidgets.remove(0);
}
}
}
public class WidgetUser extends Thread {
private WidgetMaker maker;
public WidgetUser(String name, WidgetMaker maker) {
super(name);
this.maker = maker;
}
public void run() {
while (true) {
Widget w = maker.waitForWidget();
System.out.println(getName() + " got a widget");
}
}
public static void main(String[] args) {
WidgetMaker maker = new WidgetMaker();
maker.start();
new WidgetUser("Tom", maker).start();
new WidgetUser("Jack", maker).start();
new WidgetUser("Marry", maker).start();
}
}