【Java 基础篇】Java 中的 `wait` 与 `notify` 方法详解

在 Java 中,waitnotify 方法是用于线程之间通信的重要工具。它们被用于实现线程的等待与唤醒,以及线程之间的协作。本节将深入介绍这两个方法的使用方式、作用以及一些注意事项。

wait 方法

wait 方法是 java.lang.Object 类的一个实例方法,它用于使当前线程进入等待状态,直到其他线程调用相同对象上的 notifynotifyAll 方法来唤醒它。wait 方法通常与 synchronized 关键字一起使用,以确保线程在等待时不会发生竞态条件。

wait 方法的语法

java 复制代码
public final void wait() throws InterruptedException
  • wait 方法没有参数,它将当前线程置于等待状态,直到其他线程调用相同对象上的 notifynotifyAll 方法。

  • InterruptedException 异常表示如果线程在等待过程中被中断,会抛出该异常。

wait 方法的示例

以下是一个简单的示例,演示如何使用 wait 方法等待其他线程的通知:

java 复制代码
public class WaitNotifyExample {
    public static void main(String[] args) {
        final Object lock = new Object();

        Thread waiterThread = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Waiter: Waiting for notification...");
                    lock.wait(); // 进入等待状态
                    System.out.println("Waiter: Got notified!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread notifierThread = new Thread(() -> {
            synchronized (lock) {
                try {
                    Thread.sleep(2000); // 模拟一些操作
                    System.out.println("Notifier: Notifying waiter...");
                    lock.notify(); // 唤醒等待的线程
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        waiterThread.start();
        notifierThread.start();
    }
}

在这个示例中,waiterThread 在锁定 lock 对象后调用 lock.wait() 进入等待状态,等待 notifierThread 唤醒它。

notify 方法与 notifyAll 方法

notify 方法和 notifyAll 方法都用于唤醒等待在同一个对象上的线程。主要区别在于:

  • notify 方法只会唤醒一个等待线程(无法确定是哪一个),通常用于特定条件下只需唤醒一个线程的情况。

  • notifyAll 方法会唤醒所有等待线程,通常用于多个线程都需要同时被唤醒的情况。

notify 方法的语法

java 复制代码
public final void notify()
  • notify 方法唤醒在相同对象上等待的一个线程。

notifyAll 方法的语法

java 复制代码
public final void notifyAll()
  • notifyAll 方法唤醒在相同对象上等待的所有线程。

notifynotifyAll 方法的示例

以下示例演示了如何使用 notify 方法唤醒等待线程:

java 复制代码
public class NotifyExample {
    public static void main(String[] args) {
        final Object lock = new Object();

        Thread waiterThread1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Waiter 1: Waiting for notification...");
                    lock.wait();
                    System.out.println("Waiter 1: Got notified!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread waiterThread2 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Waiter 2: Waiting for notification...");
                    lock.wait();
                    System.out.println("Waiter 2: Got notified!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread notifierThread = new Thread(() -> {
            synchronized (lock) {
                try {
                    Thread.sleep(2000);
                    System.out.println("Notifier: Notifying waiters...");
                    lock.notify(); // 唤醒等待的线程
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        waiterThread1.start();
        waiterThread2.start();
        notifierThread.start();
    }
}

在这个示例中,notifierThread 在锁定 lock 对象后调用 lock.notify() 唤醒一个等待线程,可以是 waiterThread1waiterThread2 中的任何一个。

注意事项

在使用 waitnotifynotifyAll 方法时,需要注意以下事项:

  1. 这些方法必须在 synchronized 块内调用,以确保线程安全。

  2. 线程在调用 wait 方法时会释放锁,使得其他线程可以获得锁并执行。当线程被唤醒时,它会重新尝试获得锁。

  3. 使用 wait 方法时,通常需要将它包装在一个循环中,以防止虚假唤醒(即在没有被通知的情况下线程被唤醒)。

  4. notify 方法和 notifyAll 方法不会释放锁,它们只是唤醒等待线程,等待线程被唤醒后需要重新竞争锁。

  5. notify 方法通常用于只唤醒一个线程的情况,而 notifyAll 方法用于唤醒所有等待线程的情况。

  6. 在多线程编程中,要小心死锁和竞态条件等问题,确保线程通信的安全性和正确性。

总结

希望本文能够帮助您更好地理解 waitnotify 方法在 Java 多线程编程中的作用和用法。通过合理地使用这些方法,可以实现线程之间的协作与通信,编写出更可靠的多线程程序。

相关推荐
猿来入此小猿1 分钟前
基于SpringBoot在线音乐系统平台功能实现十二
java·spring boot·后端·毕业设计·音乐系统·音乐平台·毕业源码
易码智能2 分钟前
【EtherCATBasics】- KRTS C++示例精讲(2)
开发语言·c++·kithara·windows 实时套件·krts
一只自律的鸡3 分钟前
C语言项目 天天酷跑(上篇)
c语言·开发语言
程序猿000001号6 分钟前
使用Python的Seaborn库进行数据可视化
开发语言·python·信息可视化
一个不正经的林Sir11 分钟前
C#WPF基础介绍/第一个WPF程序
开发语言·c#·wpf
愤怒的代码15 分钟前
Spring Boot对访问密钥加解密——HMAC-SHA256
java·spring boot·后端
带多刺的玫瑰15 分钟前
Leecode刷题C语言之切蛋糕的最小总开销①
java·数据结构·算法
API快乐传递者15 分钟前
Python爬虫获取淘宝详情接口详细解析
开发语言·爬虫·python
公众号Codewar原创作者17 分钟前
R数据分析:工具变量回归的做法和解释,实例解析
开发语言·人工智能·python
赵钰老师20 分钟前
基于R语言APSIM模型应用及批量模拟(精细农业、水肥管理、气候变化、粮食安全、土壤碳周转、环境影响、农业可持续性、农业生态等)
开发语言·数据分析·r语言