wait,notify,notifyAll用法解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 在并发开发中,锁是非常常见的,而wait/notify也经常会和锁一起使用,例如在生产者消费者模式中。而且wait/notify也必须和锁一起使用,因为它们都是基于对象的,否则会抛出异常。

在并发开发中,锁是非常常见的,而wait/notify也经常会和锁一起使用,例如在生产者消费者模式中。而且wait/notify也必须和锁一起使用,因为它们都是基于对象的,否则会抛出异常。
下面,我们通过一段简单的代码,来了解以下wait/notify的用法:

public class WaitNotifyTest {

    public static final Object FINAL_OBJECT = new Object();
    static class R implements Runnable{

        @Override
        public void run() {
            synchronized (FINAL_OBJECT) {
                try {
                    System.out.println(Thread.currentThread().getName()+"进入wait");
                    FINAL_OBJECT.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+"运行完成");
        }
    }

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < 3; i++) {
            new Thread(new R()).start();
        }
        Thread.sleep(100);
        synchronized (FINAL_OBJECT) {
            FINAL_OBJECT.notify();
        }
    }

}

运行结果如下:

Thread-2进入wait
Thread-4进入wait
Thread-3进入wait
Thread-2运行完成

我们发现,线程2运行完成之后,线程3和线程4还是继续会等待,所以notify方法只会唤醒一个进入wait的线程,并且是第一个进入的。如果使用notifyAll,运行结果如下:

Thread-2进入wait
Thread-3进入wait
Thread-4进入wait
Thread-4运行完成
Thread-2运行完成
Thread-3运行完成

由此我们可以分析出:使用notifyAll会将所有的线程都唤醒,唤醒之后,谁先获取到CPU资源,谁就先执行,所以这三个线程的执行顺序出现了变化。
而且,通过以上代码,我们可以知道wait的一个特性:当线程进入wait状态时,该线程会将锁资源释放,其他的线程就可以进来,而当它再次被唤醒时,就可以再次去抢夺锁资源了。

目录
相关文章
|
4天前
|
JSON Shell Linux
dockerfile 用法全解析
Dockerfile指令简介:`FROM`基于Alpine镜像;`WORKDIR`设置工作目录;`COPY`复制文件;`ADD`支持URL;`RUN`运行命令;`CMD`容器启动时执行;`ENTRYPOINT`与`CMD`组合执行;`EXPOSE`声明端口;`VOLUME`映射文件;`ENV`设置环境变量;`ARG`构建参数;`LABEL`元数据;`ONBUILD`触发命令;`STOPSIGNAL`停止信号;`HEALTHCHECK`健康检查;`SHELL`默认Shell。Alpine仅5M,小巧高效。
24 4
dockerfile 用法全解析
|
24天前
|
安全 Java
Java中WAIT和NOTIFY方法调用时机的深层解析
在Java多线程编程中,`wait()`和`notify()`方法的正确使用对于线程间的协调至关重要。这两个方法必须在同步块或同步方法中调用,这一规定的深层原因是什么呢?本文将深入探讨这一机制。
35 5
|
1月前
|
Dart 安全 编译器
Flutter结合鸿蒙next 中数据类型转换的高级用法:dynamic 类型与其他类型的转换解析
在 Flutter 开发中,`dynamic` 类型提供了灵活性,但也带来了类型安全性问题。本文深入探讨 `dynamic` 类型及其与其他类型的转换,介绍如何使用 `as` 关键字、`is` 操作符和 `whereType&lt;T&gt;()` 方法进行类型转换,并提供最佳实践,包括避免过度使用 `dynamic`、使用 Null Safety 和异常处理,帮助开发者提高代码的可读性和可维护性。
85 1
|
3月前
|
安全 网络安全 开发工具
深入探索Git:全面解析Git的用法与最佳实践
深入探索Git:全面解析Git的用法与最佳实践
67 2
|
2月前
|
前端开发 JavaScript UED
axios取消请求CancelToken的原理解析及用法示例
axios取消请求CancelToken的原理解析及用法示例
143 0
|
2月前
|
JSON API 开发者
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
22 0
|
4月前
|
Java Spring
🔥JSF 与 Spring 强强联手:打造高效、灵活的 Web 应用新标杆!💪 你还不知道吗?
【8月更文挑战第31天】JavaServer Faces(JSF)与 Spring 框架是常用的 Java Web 技术。本文介绍如何整合两者,发挥各自优势,构建高效灵活的 Web 应用。首先通过 `web.xml` 和 `ContextLoaderListener` 配置 Spring 上下文,在 `applicationContext.xml` 定义 Bean。接着使用 `@Autowired` 将 Spring 管理的 Bean 注入到 JSF 管理的 Bean 中。
73 0
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
71 2
|
2月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
76 0
|
2月前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
62 0

推荐镜像

更多
下一篇
DataWorks