先解释两个概念。
- 等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池,等待池中的线程不会去竞争该对象的锁。
- 锁池:只有获取了对象的锁,线程才能执行对象的 synchronized 代码,对象的锁每次只有一个线程可以获得,其他线程只能在锁池中等待
区别:
notify() 方法随机唤醒对象的等待池中的一个线程,进入锁池;notifyAll() 唤醒对象的等待池中的所有线程,进入锁池。
测试代码
public class TestNotifyNotifyAll { private static Object obj = new Object();public static void main(String[] args) {//测试 RunnableImplA wait()Thread t1 = new Thread(new RunnableImplA(obj));Thread t2 = new Thread(new RunnableImplA(obj));t1.start();t2.start();//RunnableImplB notify()Thread t3 = new Thread(new RunnableImplB(obj));t3.start();////RunnableImplC notifyAll()//Thread t4 = new Thread(new RunnableImplC(obj));//t4.start();}} class RunnableImplA implements Runnable { private Object obj;public RunnableImplA(Object obj) {this.obj = obj;}public void run() {System.out.println("run on RunnableImplA");synchronized (obj) {System.out.println("obj to wait on RunnableImplA");try {obj.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("obj continue to run on RunnableImplA");}}} class RunnableImplB implements Runnable { private Object obj;public RunnableImplB(Object obj) {this.obj = obj;}public void run() {System.out.println("run on RunnableImplB");System.out.println("睡眠3秒...");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (obj) {System.out.println("notify obj on RunnableImplB");obj.notify();}}} class RunnableImplC implements Runnable { private Object obj;public RunnableImplC(Object obj) {this.obj = obj;}public void run() {System.out.println("run on RunnableImplC");System.out.println("睡眠3秒...");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (obj) {System.out.println("notifyAll obj on RunnableImplC");obj.notifyAll();}}}
结果:仅调用一次 obj.notify(),线程 t1 或 t2 中的一个始终在等待被唤醒,程序不终止
run on RunnableImplAobj to wait on RunnableImplArun on RunnableImplAobj to wait on RunnableImplArun on RunnableImplB睡眠3秒...notify obj on RunnableImplBobj continue to run on RunnableImplA
把 t3 注掉,启动 t4 线程。调用 obj.notifyAll() 方法
public class TestNotifyNotifyAll { private static Object obj = new Object();public static void main(String[] args) {//测试 RunnableImplA wait()Thread t1 = new Thread(new RunnableImplA(obj));Thread t2 = new Thread(new RunnableImplA(obj));t1.start();t2.start();////RunnableImplB notify()//Thread t3 = new Thread(new RunnableImplB(obj));//t3.start();//RunnableImplC notifyAll()Thread t4 = new Thread(new RunnableImplC(obj));t4.start();}}
结果:t1、t2线程均可以执行完毕
run on RunnableImplAobj to wait on RunnableImplArun on RunnableImplAobj to wait on RunnableImplArun on RunnableImplC睡眠3秒...notifyAll obj on RunnableImplCobj continue to run on RunnableImplAobj continue to run on RunnableImplA