Java中notify()和notifyAll()的使用区别

网友投稿 313 2022-10-17


Java中notify()和notifyAll()的使用区别

notify() 和 notifyAll() 有什么区别?

先解释两个概念noGWAbJQLn。

等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池,等待池中的线程不会去竞争该对象的锁。

锁池:只有获取了对象的锁,线程才能执行对象的 synchronized 代码,对象的锁每次只有一个线程可以获得,其他线程只能在锁池中等待

然后再来说notify和notifyAll的区别

如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。

当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。也就是说,调用了notify后只要一个线程会由等待池进入锁池,而notifyAll会将该对象等待池内的所有线程移动到锁池中,等待锁竞争

优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

综上,所谓唤醒线程,另一种解释可以说是将线程由等待池移动到锁池,notifyAll调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。而notify只会唤醒一个线程。

有了这些理论基础,后面的notify可能会导致死锁,而notifyAll则不会的例子也就好解释了

测试代码

public class TestNotifyNotifyAll {

private static Object obj = new Object();

public static void main(String[] args) {

//测试 RunnableImplA wait()

Thread t1 = new Thread(new RunnoGWAbJQLnnableImplA(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 RunnableImplA

obj to wait on RunnableImplA

run on RunnableImplA

obj to wait on RunnableImplA

run on RunnableImplB

睡眠3秒...

notify obj on RunnableImplB

obj continue to run on RunnableImplA

把 t3 注掉,启动 t4 线程。调用 obj.notifyAll() 方法

public class TestNotifyNotifyAll {

private static Object obj = new Object();

noGWAbJQLnpublic 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 RunnableImplA

obj to wait on RunnableImplA

run on RunnableImplA

obj to wait on RunnableImplA

run on RunnableImplC

睡眠3秒...

notifyAll obj on RunnableImplC

obj continue to run on RunnableImplA

obj continue to run on RunnableImplA


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:能源区块链实验室受邀参加MIT Fintech年会,与校方达成多项合作意愿
下一篇:能链科技携手IBM应用基于IBM云端的Hyperledger Fabric打造碳信用管理平台
相关文章

 发表评论

暂时没有评论,来抢沙发吧~