Java线程中的wait、notify和notifyAll解析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: Java线程中的wait、notify和notifyAll解析

Java中的线程有六种状态,具体可以查看我之前的文章:Java中线程的6种状态详解(NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED)。本文主要讲其中的部分状态切换。

等待唤醒案例:线程间的通信

06_等待唤醒案例分析.bmp
顾客去包子铺买包子,告知老板自身需求后,进入等待(调用wait()方法)老板处理的过程,此时顾客的状态为
WAITING,老板做好包子后,告知(调用notify()方法)顾客包子做好了。
💡线程间的通信的主要思想是生产者消费者机制。

代码实现

思路如下:

  1. 创建一个顾客线程(消费者):告知老板要的包子的种类和数量,调用wait方法,放弃CPU的执行,进入到WAITING状态(无限等待)
  2. 创建一个老板线程(生产者):花了5秒做包子,做好包子之后,调用notify方法,唤醒顾客吃包子。

代码如下:
定义一个锁对象:

//创建锁对象,保证唯一
Object obj = new Object();

创建一个顾客线程(消费者):

// 创建一个顾客线程(消费者)
new Thread(){
    @Override
    public void run() {
        //一直等着买包子
        while(true){
            //保证等待和唤醒的线程只能有一个执行,需要使用同步技术
            synchronized (obj){
                System.out.println("顾客告知老板要的包子的种类和数量");
                //调用wait方法,放弃cpu的执行,进入到WAITING状态(无限等待)
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //唤醒之后执行的代码
                System.out.println("包子已经做好了,开吃!");
                System.out.println("---------------------------------------");
            }
        }
    }
}.start();

创建一个老板线程(生产者):

//创建一个老板线程(生产者)
new Thread(){
    @Override
    public void run() {
        //一直做包子
        while (true){
            //花了5秒做包子
            try {
                Thread.sleep(5000);//花5秒钟做包子
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //保证等待和唤醒的线程只能有一个执行,需要使用同步技术
            synchronized (obj){
                System.out.println("老板5秒钟之后做好包子,告知顾客,可以吃包子了");
                //做好包子之后,调用notify方法,唤醒顾客吃包子
                obj.notify();
            }
        }
    }
}.start();

输出如下:

顾客告知老板要的包子的种类和数量
老板5秒钟之后做好包子,告知顾客,可以吃包子了

包子已经做好了,开吃!

顾客告知老板要的包子的种类和数量
老板5秒钟之后做好包子,告知顾客,可以吃包子了

包子已经做好了,开吃!

💡注意:
顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行
同步使用的锁对象必须保证唯一
只有锁对象才能调用wait和notify方法。

扩展:Object类中wait带参方法和notifyAll方法

进入到TimeWaiting(计时等待)有两种方式

  1. 使用sleep(long m)方法,在毫秒值结束之后,线程睡醒进入到Runnable/Blocked状态
  2. 使用wait(long m)方法,wait方法如果在毫秒值结束之后,还没有被notify唤醒,就会自动醒来,线程睡醒进入到Runnable/Blocked状态

唤醒的方法:

  • void notify() 唤醒在此对象监视器上等待的单个线程。
  • void notifyAll() 唤醒在此对象监视器上等待的所有线程。
相关文章
|
2天前
|
Java
轻松上手Java字节码编辑:IDEA插件VisualClassBytes全方位解析
本插件VisualClassBytes可修改class字节码,包括class信息、字段信息、内部类,常量池和方法等。
24 6
|
2天前
|
Java
JAVA多线程通信:为何wait()与notify()如此重要?
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是实现线程间通信的核心机制。它们通过基于锁的方式,使线程在条件不满足时进入休眠状态,并在条件满足时被唤醒,从而确保数据一致性和同步。相比其他通信方式,如忙等待,这些方法更高效灵活。 示例代码展示了如何在生产者-消费者模型中使用这些方法实现线程间的协调和同步。
9 3
|
2天前
|
Java 编译器 数据库连接
Java中的异常处理机制深度解析####
本文深入探讨了Java编程语言中异常处理机制的核心原理、类型及其最佳实践,旨在帮助开发者更好地理解和应用这一关键特性。通过实例分析,揭示了try-catch-finally结构的重要性,以及如何利用自定义异常提升代码的健壮性和可读性。文章还讨论了异常处理在大型项目中的最佳实践,为提高软件质量提供指导。 ####
|
6天前
|
存储 分布式计算 Java
存算分离与计算向数据移动:深度解析与Java实现
【11月更文挑战第10天】随着大数据时代的到来,数据量的激增给传统的数据处理架构带来了巨大的挑战。传统的“存算一体”架构,即计算资源与存储资源紧密耦合,在处理海量数据时逐渐显露出其局限性。为了应对这些挑战,存算分离(Disaggregated Storage and Compute Architecture)和计算向数据移动(Compute Moves to Data)两种架构应运而生,成为大数据处理领域的热门技术。
23 2
|
6天前
|
设计模式 安全 Java
Java编程中的单例模式深入解析
【10月更文挑战第31天】在编程世界中,设计模式就像是建筑中的蓝图,它们定义了解决常见问题的最佳实践。本文将通过浅显易懂的语言带你深入了解Java中广泛应用的单例模式,并展示如何实现它。
|
5天前
|
存储 Java 开发者
Java中的集合框架深入解析
【10月更文挑战第32天】本文旨在为读者揭开Java集合框架的神秘面纱,通过深入浅出的方式介绍其内部结构与运作机制。我们将从集合框架的设计哲学出发,探讨其如何影响我们的编程实践,并配以代码示例,展示如何在真实场景中应用这些知识。无论你是Java新手还是资深开发者,这篇文章都将为你提供新的视角和实用技巧。
7 0
|
1月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
39 1
C++ 多线程之初识多线程
|
17天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
13 3
|
17天前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
13 2
|
17天前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
27 2

推荐镜像

更多
下一篇
无影云桌面