Java的wait(), notify()和notifyAll()使用心得

Java 中的 wait(), notify() 和 notifyAll() 方法

介绍

在 Java 中,线程是独立执行的,但是在某些情况下,我们希望线程之间能够进行同步和通信。这时,Java 提供了一些同步机制。其中,使用最广泛的机制就是对象的 wait()、notify() 和 notifyAll() 方法。

线程可以通过调用 wait() 方法来等待某个条件的出现,当条件不满足时,线程将被阻塞。而通过调用 notify() 或 notifyAll() 方法,又可以唤醒等待的线程。

wait() 方法

wait() 方法用于使线程等待某个条件的出现,其语法格式为:

public final void wait() throws InterruptedException

wait() 方法必须在 synchronized 块里调用。当一个线程运行到 wait() 时,它会释放对象的锁,并且线程会进入等待状态。直到另一个线程调用此对象上的 notify() 或 notifyAll() 方法,或者超时时间到期,才能继续执行。

notify() 方法

notify() 方法用于唤醒因等待某个条件而阻塞了的线程,其语法格式为:

public final void notify()

notify() 方法必须在 synchronized 块里调用。当某个线程在等待同一个对象的时候,另外一个使用同一个对象的线程调用 notify() 方法时,等待的线程会从 wait() 方法返回,继续执行。

注意:notify() 方法只能唤醒一个等待线程,具体唤醒哪个线程是随机的,不能确定。因为并不知道哪个线程最需要这个通知。

notifyAll() 方法

notifyAll() 方法用于唤醒因等待某个条件而阻塞了的所有线程,其语法格式为:

public final void notifyAll()

notifyAll() 方法必须在 synchronized 块里调用。当某个线程在等待同一个对象的时候,另外一个使用同一个对象的线程调用 notifyAll() 方法时,所有等待的线程会从 wait() 方法中返回,继续执行。

示例一

下面是一个简单的示例,演示了如何使用 wait() 和 notify() 方法来实现线程间的通信:

public class WaitNotifyDemo {
    public static void main(String[] args) {
        final Object lock = new Object();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println("Thread 1 is waiting...");
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Thread 1 is notified.");
                }
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println("Thread 2 is running...");
                    lock.notify();
                }
            }
        });
        t1.start();
        try {
            Thread.sleep(1000); // 等待一秒钟
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
    }
}

在这个示例中,有两个线程 t1 和 t2,它们使用同一个对象 lock 进行同步。线程 t1 在进入 synchronized 块后调用了 wait() 方法,导致线程被阻塞。而线程 t2 调用了 notify() 方法,唤醒了被阻塞的 t1 线程,使它重新进入就绪状态。

示例二

下面是另一个示例,演示了如何使用 wait() 和 notifyAll() 方法来实现线程间的通信:

public class WaitNotifyAllDemo {
    public static void main(String[] args) {
        final Object lock = new Object();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println("Thread 1 is waiting...");
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Thread 1 is notified.");
                }
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println("Thread 2 is waiting...");
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Thread 2 is notified.");
                }
            }
        });
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println("Thread 3 is running...");
                    lock.notifyAll(); // 唤醒所有等待的线程
                }
            }
        });
        t1.start();
        t2.start();
        try {
            Thread.sleep(1000); // 等待一秒钟
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t3.start();
    }
}

在这个示例中,有三个线程 t1、t2 和 t3,它们使用同一个对象 lock 进行同步。线程 t1 和 t2 在进入 synchronized 块后分别调用了 wait() 方法,导致线程被阻塞。而线程 t3 调用了 notifyAll() 方法,唤醒了所有被阻塞的线程,使它们重新进入就绪状态。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java的wait(), notify()和notifyAll()使用心得 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • Spring Boot应用程序中如何使用Keycloak详解

    Spring Boot应用程序中如何使用Keycloak详解 Keycloak是一个强大的、开源、易于使用的认证和授权管理解决方案。Spring Boot提供了与Keycloak的集成,可以轻松地保护和管理您的应用程序。 本文将介绍如何在Spring Boot应用程序中快速集成Keycloak,以便您的Web应用程序能够以安全的方式使用它。 准备工作 在开始…

    Java 2023年5月20日
    00
  • 宝塔面板配置及部署javaweb教程(全网最全)

    宝塔面板配置及部署javaweb教程(全网最全) 本教程介绍如何使用宝塔面板快速配置及部署javaweb应用。 步骤一:安装宝塔面板 访问宝塔官网[https://www.bt.cn/],下载适用于您服务器系统的安装包。 将下载好的安装包上传到服务器,执行安装命令。 按照提示进行安装即可。 步骤二:添加网站 登录到宝塔面板后台。 点击左侧导航栏中的“网站”,…

    Java 2023年5月19日
    00
  • java反射实现javabean转json实例代码

    Java反射实现JavaBean转JSON实例代码攻略 什么是Java反射? Java反射是指在运行时来操作Java对象的能力。通过Java反射,我们可以在运行期间分析类的内部信息,并调用类的方法、获取属性等。我们可以利用Java反射来实现一些动态编程的功能,如动态代理、依赖注入等。 如何使用Java反射实现JavaBean转JSON? JavaBean是J…

    Java 2023年5月26日
    00
  • Java深入浅出讲解String类常见方法

    Java深入浅出讲解String类常见方法攻略 String概述 在Java中,String是一种基本的数据类型,也是一种常用的数据类型。对于String类型的字符串,Java中提供了很多常见的方法,可以帮助我们对字符串进行各种操作。 String类常见方法 1. length() length()方法返回字符串的长度,即字符串中字符的个数。 示例: Str…

    Java 2023年5月26日
    00
  • 解决Idea的tomcat启动报多个listener的错误问题

    下面是详细的攻略: 问题背景 在使用IntelliJ IDEA进行Web开发时,经常需要使用内置的Tomcat容器进行开发和测试,但是在启动Tomcat容器时,经常会出现多个监听器(listener)的错误问题,该错误提示可能如下所示: SEVERE: One or more listeners failed to start. Full details w…

    Java 2023年5月19日
    00
  • Maven将代码及依赖打成一个Jar包的方式详解(最新推荐)

    下面是详细讲解Maven将代码及其依赖打成一个Jar包的完整攻略: 前提条件 在开始前,需要确保在本地预装了Maven,并已经配置好了Maven环境变量。 Step 1:创建Maven项目并导入依赖 在命令行窗口中,进入到要创建项目的目录,执行以下命令: mvn archetype:generate -DgroupId=your.group.id -Dart…

    Java 2023年6月2日
    00
  • java数组的初始化及操作详解

    Java数组的初始化及操作详解 什么是数组 在Java中,数组是一种用于存储固定数量元素的数据结构。它允许同一类型的元素存储在相邻的内存位置中,通过数字索引访问元素,可以在常量时间内访问任何一个元素。 数组的初始化 静态初始化 静态初始化是将数组在声明时进行初始化,代码格式如下: 数据类型[] 数组变量名 = {元素1, 元素2, …}; 示例: int…

    Java 2023年5月26日
    00
  • 使用Spring Boot进行单元测试详情

    使用Spring Boot进行单元测试是保证应用程序质量的重要手段。以下是使用Spring Boot进行单元测试的完整攻略: 添加测试依赖 在Spring Boot中,我们可以使用Maven或Gradle来添加测试依赖。以下是一个Maven的示例: <dependency> <groupId>org.springframework.b…

    Java 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部