java 对象的wait,notify方法是Object类定义的final方法,是无法被重写的,这两个方法的定位是多线程中,控制多个线程对共享资源的调用(典型的如生产者消费者模型), 这两种方法必须在当前线程拥有对象锁monitor的情况下使用,否则会抛出异常。
下面假设共享资源为Queue queue; 分别说明这两中方法的使用方法。
wait 方法:当前线程已经进入了同步锁的线程的情况下,让自己暂时让出同步锁,并让当前线程进入阻塞状态。以便其他正在等待此锁的线程可以得到同步锁并运行,不带参数调用wait( )==wait(0),表示无限等待,必须要其他的线程调用queue.notify()或者queue.notifyAll()方法才能唤醒。如果当前线程调用带参数方法queue.wait(1000),那么当前线程会进入阻塞,并让出同步锁。
notify/notify方法:queue.notifyAll()是当前线程通知其它所有因等待工作资源queue而进入阻塞状态的线程,告诉它们:"等待的兄弟们,我马上要用完资源了,等我释放资源后,你们就可以参与queue资源的争夺了,做好抢的整备吧"其他等待该资源的线程会收到这条"广播";queue.notify( )方法会随机的唤醒一个等待wait资源的线程。
wait和nitify通常在并发任务中配合使用的。请看下面的生产者消费者示例
package thread;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
public class ProducerConsumerInJava {
private static volatile Queue<Integer> queue = new LinkedList<Integer>();
public static void main(String[] args) {
Thread produce = new Produce(queue);
Thread consume = new Consume(queue);
produce.start();
consume.start();
}
}
class Produce extends Thread {
private Queue<Integer> queue;
public Produce(Queue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
if (queue.size() == 100) {
try {
queue.wait();// 运行了此处后,此时此刻不会执行int a=0;只有被其他线程唤醒,才会接着执行int 1=0;
int a = 0;
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
int random = new Random().nextInt();
queue.add(random);
System.out.println("生成一个产品:" + random);
}
queue.notifyAll();
}
}
}
}
class Consume extends Thread {
Queue<Integer> queue;
public Consume(Queue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
if (queue.isEmpty()) {
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
Integer remove = queue.remove();
System.out.println("消费一个产品:" + remove);
}
queue.notifyAll();
}
}
}
}