Java中的notifyAll()
方法是一个对象级别的方法,用来唤醒等待在该对象上的所有线程。当一个线程在一个对象上调用wait()
方法被阻塞时,其他线程可以在该对象上调用notify()
方法将其唤醒。但是,如果有多个线程等待在该对象上,调用notify()
方法只能随机唤醒其中一个线程。为了唤醒等待在该对象上的所有线程,我们需要使用notifyAll()
方法。
notifyAll()
方法具有以下特性:
notifyAll()
方法唤醒该对象上所有被阻塞的线程,从而达到通知所有线程的效果。- 唤醒的线程会进入到对象的锁池中竞争锁,竞争成功的线程会执行,竞争失败的线程仍然被阻塞
- 调用
notifyAll()
方法只有在拥有该对象的引用的synchronized块或方法中才能被调用
以下是示例代码说明:
- 基本使用示例
public class notifyAllExample {
public static void main(String[] args) {
final Object lock = new Object();
new Thread(() -> {
synchronized (lock) {
try {
System.out.println("Thread 1 is waiting...");
lock.wait();
System.out.println("Thread 1 has been notified...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(() -> {
synchronized (lock) {
try {
System.out.println("Thread 2 is waiting...");
lock.wait();
System.out.println("Thread 2 has been notified...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(() -> {
synchronized (lock) {
System.out.println("Thread 3 is notifying...");
lock.notifyAll();
}
}).start();
}
}
在以上示例中,我们创建了3个线程,其中前两个线程在锁对象上调用wait()
方法被阻塞。第三个线程在锁对象上调用notifyAll()
方法唤醒所有的线程,这样被阻塞的线程就会继续执行,输出下面的结果:
Thread 1 is waiting...
Thread 2 is waiting...
Thread 3 is notifying...
Thread 1 has been notified...
Thread 2 has been notified...
- 解决死锁
public class DeadlockSolution {
Object lock1 = new Object();
Object lock2 = new Object();
public void method1() {
synchronized (lock1) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("method1");
}
}
}
public void method2() {
synchronized (lock2) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock1) {
System.out.println("method2");
}
}
}
public static void main(String[] args) {
DeadlockSolution d = new DeadlockSolution();
new Thread(() -> d.method1()).start();
new Thread(() -> d.method2()).start();
synchronized (d.lock1){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
d.lock1.notifyAll();
}
}
}
在以上示例中,我们创建了两个方法method1()
和method2()
,两个方法分别持有对象锁lock1
和lock2
,并且相互依赖。我们同时创建了两个线程分别去执行method1()
和method2()
,这样就形成了死锁。我们在main方法中通过调用notifyAll()
方法,通知所有被阻塞的线程,解除死锁状态,输出结果:
method1
method2
我们可以看到,线程成功地执行了两个方法,这样就成功解除了代码的死锁状态。