在 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 多线程程序的性能和可靠性。