JAVA --- notify 和 notifyAll 有什么区别?

notifynotifyAll是Java中用于线程间通信的方法,它们都属于Object类,用于唤醒正在等待该对象锁的线程。尽管它们的目的相似,但在行为和使用场景上有显著的区别。

notify方法随机唤醒一个正在等待该对象锁的线程,适用于只需要一个线程继续执行的场景。而notifyAll方法唤醒所有正在等待该对象锁的线程,适用于需要所有线程都尝试继续执行的场景。使用notifyAll可能会导致大量的线程被唤醒并竞争锁,可能会影响性能,因此应该谨慎使用。

notify 方法

  1. 唤醒单个线程

    • notify方法随机唤醒一个正在等待该对象锁的线程。具体唤醒哪个线程是不确定的,由JVM决定。
  2. 适用场景

    • 当有多个线程等待同一个对象锁,但只需要其中一个线程继续执行时,可以使用notify。例如,生产者-消费者问题中,生产者只需要唤醒一个消费者线程来处理新生产的产品。
  3. 注意事项

    • 使用notify时需要确保唤醒的线程能够正确处理当前的状态,否则可能会导致逻辑错误。

notifyAll 方法

  1. 唤醒所有线程

    • notifyAll方法唤醒所有正在等待该对象锁的线程。所有被唤醒的线程会竞争该对象的锁,只有一个线程能够获得锁并继续执行,其他线程将继续等待。
  2. 适用场景

    • 当有多个线程等待同一个对象锁,并且需要所有线程都尝试继续执行时,可以使用notifyAll。例如,多个消费者线程等待新的产品,当有新产品时,所有消费者线程都应该被唤醒尝试获取产品。
  3. 注意事项

    • 使用notifyAll可能会导致大量的线程被唤醒并竞争锁,可能会影响性能。因此,应该谨慎使用,确保在确实需要唤醒所有线程时才使用。

示例代码

notify 示例
public class NotifyExample {
    public static void main(String[] args) {
        final Object lock = new Object();

        Thread waitingThread1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Thread 1 is going to wait.");
                    lock.wait();
                    System.out.println("Thread 1 woke up.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread waitingThread2 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Thread 2 is going to wait.");
                    lock.wait();
                    System.out.println("Thread 2 woke up.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread notifyingThread = new Thread(() -> {
            synchronized (lock) {
                System.out.println("Notifying one thread.");
                lock.notify();
            }
        });

        waitingThread1.start();
        waitingThread2.start();
        try {
            Thread.sleep(1000); // 确保等待线程先进入等待状态
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        notifyingThread.start();
    }
}
notifyAll 示例
public class NotifyAllExample {
    public static void main(String[] args) {
        final Object lock = new Object();

        Thread waitingThread1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Thread 1 is going to wait.");
                    lock.wait();
                    System.out.println("Thread 1 woke up.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread waitingThread2 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Thread 2 is going to wait.");
                    lock.wait();
                    System.out.println("Thread 2 woke up.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread notifyingThread = new Thread(() -> {
            synchronized (lock) {
                System.out.println("Notifying all threads.");
                lock.notifyAll();
            }
        });

        waitingThread1.start();
        waitingThread2.start();
        try {
            Thread.sleep(1000); // 确保等待线程先进入等待状态
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        notifyingThread.start();
    }
}

总结

  • notify:随机唤醒一个正在等待该对象锁的线程,适用于只需要一个线程继续执行的场景。
  • notifyAll:唤醒所有正在等待该对象锁的线程,适用于需要所有线程都尝试继续执行的场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

需要重新演唱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值