notify() 和 notifyAll() 有什么区别?
notify() 和 notifyAll() 有什么区别?
先解释两个概念。
- 等待池:假设一个线程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 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();
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 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
【Java面试题与答案】整理推荐
- 基础与语法
- 集合
- 网络编程
- 并发编程
- Web
- 安全
- 设计模式
- 框架
- 算法与数据结构
- 异常
- 文件解析与生成
- Linux
- MySQL
- Oracle
- Redis
- Dubbo
vd_vd: 只有我觉得答得不错吗
啦啦啦hh: NIO的含义是不是写错了
我不是小白啊: [code=plain] SHUTDOWN 状态下,任务数为 0, 其他所有任务已终止,线程池会变为 TIDYING 状态,会执行 terminated() 方法。线程池中的 terminated() 方法是空实现,可以重写该方法进行相应的处理。 线程池在 SHUTDOWN 状态,任务队列为空且执行中任务为空,线程池就会由 SHUTDOWN 转变为 TIDYING 状态。 [/code] 这俩感觉意思一样呢,都是搜友任务都执行完了。
CSDN-Ada助手: 多亏了你这篇博客, 解决了问题: https://ask.csdn.net/questions/8039802, 请多输出高质量博客, 帮助更多的人
飞羽疾驰: 可以的,我看的另一篇,面试时90%以上的题目都在下边这个文章里:https://knife.blog.csdn.net/article/details/121219272