概述
notify()
和 notifyAll()
是 Object
类中的方法,用于在多线程环境中唤醒正在等待该对象监视器的线程。
notify()
notify()
方法唤醒正在等待该对象监视器的单个线程。被唤醒的线程是任意的,由 Java 虚拟机 (JVM) 选择。
notifyAll()
notifyAll()
方法唤醒正在等待该对象监视器的所有线程。所有被唤醒的线程都将争用该对象的锁,并且其中只有一个线程可以继续执行。
用法
notify()
和 notifyAll()
方法通常在以下情况下使用:
- 当一个线程修改了共享数据,并且需要通知其他正在等待该数据的线程时。
- 当一个线程释放了对共享资源的锁,并且需要通知其他正在等待该资源的线程时。
示例
以下示例演示了如何使用 notify()
和 notifyAll()
方法:
public class MyThread extends Thread {
private Object lock = new Object();
@Override
public void run() {
synchronized (lock) {
try {
// 等待其他线程通知
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 执行线程逻辑
}
}
}
public class Main {
public static void main(String[] args) {
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
thread1.start();
thread2.start();
// 唤醒一个线程
synchronized (thread1.lock) {
thread1.lock.notify();
}
// 唤醒所有线程
synchronized (thread2.lock) {
thread2.lock.notifyAll();
}
}
}
在这个示例中,两个线程 thread1
和 thread2
都在等待 lock
对象上的通知。主线程使用 notify()
方法唤醒 thread1
,并使用 notifyAll()
方法唤醒 thread2
。
何时使用 notify()
使用 notify()
方式适用于以下情况:
- 只需要唤醒一个正在等待的线程。
- 不需要确定被唤醒的线程。
何时使用 notifyAll()
使用 notifyAll()
方式适用于以下情况:
- 需要唤醒所有正在等待的线程。
- 想要让所有线程争用对象的锁。
性能考虑
使用 notifyAll()
方法比 notify()
方法的性能开销更大,因为它需要唤醒所有正在等待的线程。因此,在只需要唤醒一个线程的情况下,应优先使用 notify()
方法。
最佳实践
使用 notify()
和 notifyAll()
方法时,应遵循以下最佳实践:
- 始终在同步块内调用
notify()
和notifyAll()
方法。 - 确保被唤醒的线程能够正确处理通知。
- 避免在循环中重复调用
notify()
或notifyAll()
方法,因为这可能会导致性能问题。
总结
notify()
和 notifyAll()
方法是 Java 中用于在多线程环境中唤醒线程的重要工具。了解两者的区别以及何时使用每个方法至关重要,以编写有效且可维护的多线程应用程序。