原创

java面试题-notify()和notifyAll()有什么区别?

在Java多线程编程中,notify()notifyAll() 是两个重要的方法,用于线程间的通信。这两个方法都与对象的锁池和等待池有关,但在使用时需要注意它们之间的区别。本教程将详细讨论notify()notifyAll() 的概念、区别,并提供相应的代码示例,帮助初学者更好地理解这两个方法的使用。

1. 等待池和锁池的概念

在深入讨论 notify()notifyAll() 之前,我们需要理解两个重要的概念:

  • 等待池: 当一个线程调用某个对象的 wait() 方法时,该线程会释放该对象的锁并进入等待池。等待池中的线程不会去竞争对象的锁。

  • 锁池: 只有获得了对象的锁,线程才能执行对象的 synchronized 代码。对象的锁每次只能被一个线程获取,其他线程只能在锁池中等待。

2. notify() 和 notifyAll() 的区别

2.1 notify()

  • notify() 方法用于随机唤醒对象的等待池中的一个线程,使其进入锁池。

2.2 notifyAll()

  • notifyAll() 方法用于唤醒对象的等待池中的所有线程,使它们都进入锁池。

3. 示例代码演示

public class TestNotifyNotifyAll {
    private static Object obj = new Object();

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            System.out.println("t1 开始执行");
            synchronized (obj) {
                try {
                    System.out.println("t1 开始等待");
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("t1 结束执行");
        });

        Thread t2 = new Thread(() -> {
            System.out.println("t2 开始执行");
            synchronized (obj) {
                try {
                    System.out.println("t2 开始等待");
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("t2 结束执行");
        });

        t1.start();
        t2.start();

        // 启动 t3 线程,调用 notify() 方法
        Thread t3 = new Thread(() -> {
            synchronized (obj) {
                System.out.println("随机唤醒其他线程");
                obj.notify();
            }
        });
        t3.start();

        // 启动 t4 线程,调用 notifyAll() 方法
        Thread t4 = new Thread(() -> {
            synchronized (obj) {
                System.out.println("唤醒其他所有线程");
                obj.notifyAll();
            }
        });
        t4.start();
    }
}

4. 代码解释

  • t1t2 线程分别调用 obj.wait() 进入等待池,等待被唤醒。
  • t3 线程调用 obj.notify() 随机唤醒 t1t2 中的一个线程。
  • t4 线程调用 obj.notifyAll() 唤醒所有等待池中的线程。

5. 执行结果

执行以上代码,将得到如下输出:

t1 开始执行
t1 开始等待
t2 开始执行
t2 开始等待
随机唤醒其他线程
唤醒其他所有线程
t2 结束执行
t1 结束执行

6. 总结

通过本教程,我们深入理解了 notify()notifyAll() 方法在Java中的用法和区别。了解这两个方法对于更好地处理多线程编程中的线程通信至关重要,确保在适当的时候唤醒等待池中的线程。

正文到此结束
本文目录