考虑一个生产者/消费者模型。
商品类Goods:
class Goods {
private String name;
public Goods(String name) { this.name =name; }
public String toString() { return "Goods[" + name + ']'; }
}
商品容器类GoodsStatck:
class GoodsStatck{
private Goods[]buffer;
int point =-1;
int size;
GoodsStatck (int size) { this.size = size; buffer = new Goods[size]; }
public synchronized int getPoint() { return this.point; }
public synchronized Goods pop() {
if (point<0) {
return null;
}
Goods goods = buffer[point];
buffer[point] = null;
point--;
return goods;
}
public synchronized boolean push(Goods goods){
if (point>= size - 1) {
return false;
}
point++;
buffer[point] = goods;
return true;
}
}
生产者类Producer:
class Producer implements Runnable{
private GoodsStatck goodsStatck;
private String name;
Producer(String name, GoodsStatck goodsStatck) {
this.name = name;
this.goodsStatck = goodsStatck;
}
public void run(){
while (true) {
synchronized (this.goodsStatck) {
Goods goods = new Goods("No-" + (this.goodsStatck.getPoint() +1));
boolean result =this.goodsStatck.push(goods);
if (result) {
System.out.println(name + " produce : " + goods);
}
else{
System.err.println("Error! The stack is full");
}
}
}
}
}
消费者类Producer:
class Consumer implements Runnable{
private GoodsStatck goodsStatck;
private String name;
Consumer(String name, GoodsStatck goodsStatck) {
this.name =name;
this.goodsStatck =goodsStatck;
}
public void run(){
while (true) {
Goods goods =this.goodsStatck.pop();
if (goods !=null) {
System.out.println(name + " get : " + goods);
}else {
System.err.println("Error! There is no goods in stack ");
}
}
}
}
测试程序:
GoodsStatck goodsStatck = new GoodsStatck(2);
Producer producer1 = new Producer("producer-1",goodsStatck);
Producer producer2 = new Producer("producer-2",goodsStatck);
Consumer consumer1 = new Consumer("consumer-1",goodsStatck);
Consumer consumer2 = new Consumer("consumer-2",goodsStatck);
new Thread(producer1).start();
new Thread(producer2).start();
new Thread(consumer1).start();
new Thread(consumer2).start();
可能出现以下输出:
Error!The stack is full
Error!There is no goods in stack
即在push的时候会遇到容器GoodsStatck已满,pop的时候遇到容器GoodsStatck为空的情况。
要改变这种情况,必须使用wait()/notify(),即将GoodsStatck的pop()、push() 修改如下:
public synchronized Goods pop() {
this.notifyAll();
while (point<0) {
try {
this.wait();
}catch (InterruptedException ex) { throw new RuntimeException(ex); }
}
Goods goods = buffer[point];
buffer[point] = null;
point--;
return goods;
}
public synchronized boolean push(Goods goods){
this.notifyAll();
while (point>= size - 1) {
try {
this.wait();
}catch (InterruptedException ex) { throw new RuntimeException(ex); }
}
point++;
buffer[point] = goods;
return true;
}
这样在遇到容器GoodsStatck为空或满的情况时(while循环中),线程将放弃锁(GoodsStatck.this)阻塞,直到满足条件。使用时候注意:
1. 先唤醒其他线程,再放弃自己的锁,即先notify()/notifyAll(),再wait()
2. wait() 方法必须放在while循环中,不能放在if条件中
3. 一般情况下,notifyAll() 优于notify()。
可以用 java.util.concurrent包中阻塞队列 BlockingQueue(interface) 实现 ( LinkedBlockingDeque(class), ArrayBlockingQueue (class) , PriorityBlockingQueue (class))