线程交互
有时线程之间有交互通知的需求,例如生产者消费者问题。生产者每次生产一个商品,消费者每次消耗一个商品;当商品数目为0的时候,消费者线程需要等待生产者生产出商品,才能继续运行;当商品数目达到上限时,生产者线程需要等待消费者消耗了商品。才可以继续运行。
在操作系统中,上述思想采用的是信号量机制以及PV操作,对应Java中的wait() 和 notify() 方法:
wait() :让当前占用了某个对象的线程,暂时进入等待状态,并释放掉当前的占用。等待其他进程的notify() 将它唤醒。注意,wait() 方法只能使用在synchronized块中。
notify() :通知一个等待在当前同步对象上的线程,告诉他可以醒了,并有机会占用当前对象。
notifyAll() :通知所有等待当前同步对象的上的线程,告诉他们可以醒了,并有机会占用当前对象。
生产者消费者问题
首先看一段代码:
class Store {
final int capacity = 8; //item容量为8
int item; //当前商品个数
public Store(int item) {
this.item = item;
}
//生产者方法,每次生产一个item
public synchronized void produce() {
//如果仓库满了,则wait(),等待消费者消费
if(item == capacity) {
try {
this.wait();
}catch (Exception e) {
e.printStackTrace();
}
}
item += 1;
//生产者生产了商品,告诉消费者你们可以消费了
this.notify();
System.out.println("生产后的量为:" + this.item);
}
//消费者方法,每次消耗一个item
public synchronized void consume() {
//商品为空的时候,消费者开始等待
if(item == 0) {
try {
this.wait();
}catch (Exception e) {
e.printStackTrace();
}
}
item -= 1;
//消费者通知生产者,你们可以继续生产了
this.notify();
System.out.println("消费后的量为:" + this.item);
}
}
注意,wait()方法和notify()方法并不是线程类Thread的方法,而是超类Object中的方法。因此所有的Object都可以被用作同步对象。因此准确来说,wait()和notify()是同步对象的方法。