在 Java 并发编程中,锁的等待和唤醒机制至关重要,通常使用 wait()、notify() 和 notifyAll() 来实现线程间的协调。本文将详细介绍这些方法的用法,并通过示例代码加以说明。
1. wait()、notify() 与 notifyAll()
在 Java 中,Object 类提供了 wait()、notify() 和 notifyAll() 方法,它们用于线程间的通信。
wait():使当前线程进入等待状态,并释放锁。notify():唤醒单个等待线程。notifyAll():唤醒所有等待线程。
注意,这些方法必须在同步代码块(synchronized)中调用,否则会抛出 IllegalMonitorStateException。
2. 示例代码
下面的示例展示了 wait() 和 notify() 的使用。
class SharedResource {private boolean available = false;public synchronized void produce() {while (available) {try {wait();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}System.out.println("Producing an item");available = true;notify();}public synchronized void consume() {while (!available) {try {wait();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}System.out.println("Consuming an item");available = false;notify();}
}public class WaitNotifyExample {public static void main(String[] args) {SharedResource resource = new SharedResource();Thread producer = new Thread(resource::produce);Thread consumer = new Thread(resource::consume);producer.start();consumer.start();}
}
3. wait() 和 notify() 的工作原理
- 生产者线程
produce()在available为true时调用wait()进入等待状态,释放锁。 - 消费者线程
consume()在available为false时调用wait()进入等待状态,释放锁。 produce()生产后调用notify()唤醒consume()。consume()消费后调用notify()唤醒produce()。
4. notifyAll() 的使用场景
notify() 仅唤醒一个线程,而 notifyAll() 可用于有多个等待线程的情况,以防止某些线程被永久阻塞。
public synchronized void produce() {while (available) {try {wait();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}System.out.println("Producing an item");available = true;notifyAll();
}
5. Lock 和 Condition 方式
除了 synchronized,还可以使用 Lock 和 Condition 进行等待和唤醒控制。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;class SharedResourceWithLock {private boolean available = false;private final Lock lock = new ReentrantLock();private final Condition condition = lock.newCondition();public void produce() {lock.lock();try {while (available) {condition.await();}System.out.println("Producing an item");available = true;condition.signal();} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {lock.unlock();}}public void consume() {lock.lock();try {while (!available) {condition.await();}System.out.println("Consuming an item");available = false;condition.signal();} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {lock.unlock();}}
}
6. 总结
wait()和notify()需要在synchronized块中使用。notifyAll()可防止线程被永久阻塞。Lock和Condition提供更灵活的等待和唤醒机制。
合理使用这些机制可以提升 Java 多线程程序的性能和可靠性。