【Java|多线程与高并发】wait和notify方法详解

简介: 在Java多线程环境中,线程之间是抢占式执行的,线程的调度是随机的.这就很难受了. 在很多情况下我们希望线程以我们想要的顺序来执行. 这就需要wait和notify这两个方法

1.前言

在Java多线程环境中,线程之间是抢占式执行的,线程的调度是随机的.这就很难受了. 在很多情况下我们希望线程以我们想要的顺序来执行. 这就需要wait和notify这两个方法


59e74b222c014ea48c8781bd1e93dea1.gif


2.wait和notify的基本使用

首先是wait方法



736769a8005645fb985f554ba91dc32b.png

wait是Object类的方法,而Java中的类都是间接或直接继承于Object类. 因此只要是类的实例都可以调用wait方法


运行上述代码:

12a82e2f34594edfb0f5cef7439fed4a.png



可以看到这里抛出了一个 非法的锁状态异常


其实wait方法的执行分为三步:


1.释放当前锁

2.进行等待通知

3.满足一定的条件(其它线程调用notify),被唤醒,然后重新获取锁

什么要先释放锁,再进行等待通知呢?


因为wait如果不释放锁,可能会影响到其它线程的执行,就是为了保证不影响其它线程的执行


因此wait与锁密不可分

09135b0ed76f4582a16289021bd61180.png



对上述代码进行加锁,就不会抛出异常了.


但上述代码的执行并没有结束,因为线程在调用wait方法之后,会一直处于阻塞状态,直到有其它线程调用notify方法为止.

而调用notify方法的线程要和调用wait方法的线程是针对同一个对象进行加锁的才行.


示例:

    public static void main(String[] args) {
        Object object = new Object();
        Thread t1 = new Thread(() ->{
            while(true){
                synchronized (object){
                    System.out.println("wait 之前");
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println("wait 之后");
                }
            }
        });
        t1.start();
        Thread t2 = new Thread(() ->{
            while(true){
                synchronized (object){
                    System.out.println("notify 之前");
                    object.notify();
                    System.out.println("notify 之后");
                }
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t2.start();
    }

运行截图:

736966ed0cbe4c5da5711b3ad34b8838.png



上述标注的是一组 wait和notify方法的执行流程.


注: 如果先调用的是notify方法,代码并不会有什么影响.


3. notifyAll方法

Java中除了使用notify方法唤醒线程,还有一个notifyAll方法.

当一个线程调用了某个对象的notifyAll方法后,该对象上的所有等待线程将被唤醒,即使唤醒了所有在等待的线程,这些线程之间也要进行锁竞争(串行执行)。


4. wait和sleep方法的对比

wait方法和sleep方法的对比也是面试中经常会问到的问题


对于这个问题,可以从相同点和不同点进行回答:


相同点: 都是让线程进入阻塞等待状态

不同点:sleep方法是通过时间来通知唤醒,而wait方法则需要使用notify或notifyAll进行唤醒


5. 总结

wait和notify方法用于实现线程间的协作和通信.

wait方法使线程进入等待状态,notify方法唤醒一个等待线程,notifyAll方法唤醒所有等待线程。

通过上述三个方法,可以使线程按照特定的顺序执行或者等待某个条件满足后再执行。

9a81996bb66b41ceb0fa838d5b6aafcc.gif


相关文章
|
5月前
|
安全 算法 Java
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
213 0
|
3月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
|
6月前
|
缓存 监控 Cloud Native
Java Solon v3.2.0 高并发与低内存实战指南之解决方案优化
本文深入解析了Java Solon v3.2.0框架的实战应用,聚焦高并发与低内存消耗场景。通过响应式编程、云原生支持、内存优化等特性,结合API网关、数据库操作及分布式缓存实例,展示其在秒杀系统中的性能优势。文章还提供了Docker部署、监控方案及实际效果数据,助力开发者构建高效稳定的应用系统。代码示例详尽,适合希望提升系统性能的Java开发者参考。
312 4
Java Solon v3.2.0 高并发与低内存实战指南之解决方案优化
|
5月前
|
缓存 NoSQL Java
Java 项目实操高并发电商系统核心模块实现从基础到进阶的长尾技术要点详解 Java 项目实操
本项目实战实现高并发电商系统核心模块,涵盖商品、订单与库存服务。采用Spring Boot 3、Redis 7、RabbitMQ等最新技术栈,通过秒杀场景解决库存超卖、限流熔断及分布式事务难题。结合多级缓存优化查询性能,提升系统稳定性与吞吐能力,适用于Java微服务开发进阶学习。
172 0
|
6月前
|
Java 数据挖掘 调度
Java 多线程创建零基础入门新手指南:从零开始全面学习多线程创建方法
本文从零基础角度出发,深入浅出地讲解Java多线程的创建方式。内容涵盖继承`Thread`类、实现`Runnable`接口、使用`Callable`和`Future`接口以及线程池的创建与管理等核心知识点。通过代码示例与应用场景分析,帮助读者理解每种方式的特点及适用场景,理论结合实践,轻松掌握Java多线程编程 essentials。
395 5
|
6月前
|
监控 搜索推荐 Java
Java 多线程最新实操技术与应用场景全解析:从基础到进阶
本文深入探讨了Java多线程的现代并发编程技术,涵盖Java 8+新特性,如CompletableFuture异步处理、Stream并行流操作,以及Reactive编程中的Reactor框架。通过具体代码示例,讲解了异步任务组合、并行流优化及响应式编程的核心概念(Flux与Mono)。同时对比了同步、CompletableFuture和Reactor三种实现方式的性能,并总结了最佳实践,帮助开发者构建高效、扩展性强的应用。资源地址:[点击下载](https://pan.quark.cn/s/14fcf913bae6)。
398 3
|
7月前
|
算法 Java 调度
Java多线程基础
本文主要讲解多线程相关知识,分为两部分。第一部分涵盖多线程概念(并发与并行、进程与线程)、Java程序运行原理(JVM启动多线程特性)、实现多线程的两种方式(继承Thread类与实现Runnable接口)及其区别。第二部分涉及线程同步(同步锁的应用场景与代码示例)及线程间通信(wait()与notify()方法的使用)。通过多个Demo代码实例,深入浅出地解析多线程的核心知识点,帮助读者掌握其实现与应用技巧。
139 1
|
7月前
|
Java
java 多线程异常处理
本文介绍了Java中ThreadGroup的异常处理机制,重点讲解UncaughtExceptionHandler的使用。通过示例代码展示了当线程的run()方法抛出未捕获异常时,JVM如何依次查找并调用线程的异常处理器、线程组的uncaughtException方法或默认异常处理器。文章还提供了具体代码和输出结果,帮助理解不同处理器的优先级与执行逻辑。
174 1
|
9月前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
366 23

热门文章

最新文章