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日

相关文章

  • java全角、半角字符的关系以及转换详解

    Java中的字符类型是char,我们通常所见的字符分为全角和半角字符。 在Java中,半角字符在字符编码中仅占一个字节(即8位),而全角字符一般占两个字节(即16位),因此在处理含有全角字符的字符串时,需要进行字符转换。 Java提供了转换半角为全角以及转换全角为半角的方法。其中半角转全角主要使用的是将字符Unicode码值增加65248(0xFEE0)来实…

    Java 2023年5月27日
    00
  • 使用maven的profile构建不同环境配置的方法

    使用maven的profile构建不同环境配置的方法,一般分以下几个步骤: 配置pom.xml文件 在pom.xml文件中添加不同环境的profile,例如: <profiles> <!– 开发环境 — > <profile> <id>dev</id> <properties> &l…

    Java 2023年5月19日
    00
  • 更改MySQL数据库的编码为utf8mb4问题

    更改MySQL数据库的编码为utf8mb4需要经历以下几个步骤: 1. 检查MySQL数据库当前编码 在终端或命令行中运行以下命令: mysql -u 用户名 -p 接着输入你的密码登录MySQL数据库,然后执行以下查询语句检查当前数据库编码: SHOW VARIABLES LIKE ‘%character%’; 2. 备份MySQL数据库 在进行更改编码之…

    Java 2023年5月20日
    00
  • Sprint Boot @SpringBootApplication使用方法详解

    @SpringBootApplication是Spring Boot中的一个注解,它是一个组合注解,包含了@Configuration、@EnableAutoConfiguration和@ComponentScan三个注解。在Spring Boot应用程序中,通常会使用@SpringBootApplication注解来标记主类,以启用自动配置和组件扫描。本文…

    Java 2023年5月5日
    00
  • 浅谈java监听器的作用

    浅谈Java监听器的作用 什么是监听器 在Java中,监听器是一种常见的设计模式,它可以让我们在某个事件发生时,自动触发执行一些操作。 监听器的作用 Java监听器的作用主要有以下几点: 可以在特定的事件发生时,自动触发一些操作。 可以对代码的业务逻辑和程序的功能进行解耦,提高代码的复用性。 可以使代码更加灵活和可控,方便维护。 监听器的相关类 Java中提…

    Java 2023年6月15日
    00
  • java字节字符转换流操作详解

    Java字节字符转换流操作详解 什么是Java字节字符转换流? Java字节字符转换流是Java I/O API中的一种高级流(也叫过滤流或处理流),用于在字节流和字符流之间进行转换。在Java中,通常使用字节流来处理二进制数据文件、图像文件和音频文件等等,而使用字符流来处理文本文件。但是在实际开发中,我们可能需要将字节流转换成字符流或将字符流转换成字节流。…

    Java 2023年5月20日
    00
  • 浅析Redis中String数据类型及其底层编码

    浅析Redis中String数据类型及其底层编码 String数据类型介绍 Redis中String数据类型是最基本、最常用的数据类型之一,它可以保存字符串、整数或者浮点数。String类型可以进行增删改查等常见操作,支持的操作包括SET、GET、INCR等。 String数据类型底层编码 Redis中,对于每一种数据类型,都有对应的底层编码方式,Strin…

    Java 2023年6月1日
    00
  • spring注解 @PropertySource配置数据源全流程

    Spring注解 @PropertySource 用于加载指定的属性源,是Spring Framework 4.0版本之后提供的新特性。它允许我们从外部文件或环境变量中读取配置信息,灵活地管理我们的应用程序的数据源。 下面是使用 @PropertySource 配置数据源的完整流程: 引入依赖 在项目的 pom.xml 文件中添加以下依赖: <depe…

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