在JDK中,定义了wait(), notify()和notifyAll()等接口。wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。而notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。
wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视。本文对这些关键字的使用进行了描述。
在 Java 中可以用 wait、notify 和 notifyAll 来实现线程间的通信。。举个例子,如果你的Java程序中有两个线程——即生产者和消费者,那么生产者可以通知消费者,让消费者开始消耗数据,因为队列缓冲区中有内容待消费(不为空)。相应的,消费者可以通知生产者可以开始生成更多的数据,因为当它消耗掉某些数据后缓冲区不再为满。
我们可以利用wait()来让一个线程在某些条件下暂停运行。例如,在生产者消费者模型中,生产者线程在缓冲区为满的时候,消费者在缓冲区为空的时候,都应该暂停运行。如果某些线程在等待某些条件触发,那当那些条件为真时,你可以用 notify 和 notifyAll 来通知那些等待中的线程重新开始运行。不同之处在于,notify 仅仅通知一个线程,并且我们不知道哪个线程会收到通知,然而 notifyAll 会通知所有等待中的线程。换言之,如果只有一个线程在等待一个信号灯,notify和notifyAll都会通知到这个线程。但如果多个线程在等待这个信号灯,那么notify只会通知到其中一个,而其它线程并不会收到任何通知,而notifyAll会唤醒所有等待中的线程。
package com.test.thread;
class TestThread extends Thread{
public TestThread(String name) {
super(name);
}
public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName()+"notify_唤醒监视器等待的单个线程");
notify();
}
}
}
public class Wait_Notify_Test {
public static void main(String[] args) {
TestThread t1 = new TestThread("t1");
synchronized(t1) {
try {
System.out.println(Thread.currentThread().getName()+"开始执行!!!");
t1.start();
System.out.println(Thread.currentThread().getName()+"进入等待状态");
t1.wait();
System.out.println(Thread.currentThread().getName()+" continue");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//==============wait 和notifyAll()
package com.test.thread;
public class Wait_NotifyALL_Test {
private static Object object = new Object();
public static void main(String[] args) {
TestThread t1 = new TestThread("t1");
TestThread t2 = new TestThread("t2");
TestThread t3 = new TestThread("t3");
t1.start();
t2.start();
t3.start();
try {
System.out.println(Thread.currentThread().getName()+"__线程休眠2秒");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(object) {
System.out.println(Thread.currentThread().getName()+"__唤醒所有的等待的线程让他们 去竞争");
object.notifyAll();
}
}
static class TestThread extends Thread{
public TestThread(String name){
super(name);
}
public void run() {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + "__线程进入等待...");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "__唤醒成功执行");
}
}
}
}