notify
和notifyAll
是Java中用于线程间通信的方法,它们都属于Object
类,用于唤醒正在等待该对象锁的线程。尽管它们的目的相似,但在行为和使用场景上有显著的区别。
notify
方法随机唤醒一个正在等待该对象锁的线程,适用于只需要一个线程继续执行的场景。而notifyAll
方法唤醒所有正在等待该对象锁的线程,适用于需要所有线程都尝试继续执行的场景。使用notifyAll
可能会导致大量的线程被唤醒并竞争锁,可能会影响性能,因此应该谨慎使用。
notify
方法
-
唤醒单个线程:
notify
方法随机唤醒一个正在等待该对象锁的线程。具体唤醒哪个线程是不确定的,由JVM决定。
-
适用场景:
- 当有多个线程等待同一个对象锁,但只需要其中一个线程继续执行时,可以使用
notify
。例如,生产者-消费者问题中,生产者只需要唤醒一个消费者线程来处理新生产的产品。
- 当有多个线程等待同一个对象锁,但只需要其中一个线程继续执行时,可以使用
-
注意事项:
- 使用
notify
时需要确保唤醒的线程能够正确处理当前的状态,否则可能会导致逻辑错误。
- 使用
notifyAll
方法
-
唤醒所有线程:
notifyAll
方法唤醒所有正在等待该对象锁的线程。所有被唤醒的线程会竞争该对象的锁,只有一个线程能够获得锁并继续执行,其他线程将继续等待。
-
适用场景:
- 当有多个线程等待同一个对象锁,并且需要所有线程都尝试继续执行时,可以使用
notifyAll
。例如,多个消费者线程等待新的产品,当有新产品时,所有消费者线程都应该被唤醒尝试获取产品。
- 当有多个线程等待同一个对象锁,并且需要所有线程都尝试继续执行时,可以使用
-
注意事项:
- 使用
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
:唤醒所有正在等待该对象锁的线程,适用于需要所有线程都尝试继续执行的场景。