在Java中,wait()
和 notify()
是用于线程间协作和同步的重要方法,它们都定义在 java.lang.Object
类中。这两个方法必须在 synchronized
同步块或方法中使用,因为它们依赖于对象的监视器(monitor),只有持有对象监视器的线程才能调用这些方法。
下面是一个简单的例子,展示如何在一个生产者消费者模型中使用 synchronized
、wait()
和 notify()
方法:
import java.util.LinkedList;
public class ProducerConsumer {
private final LinkedList<Integer> buffer = new LinkedList<>();
private static final int BUFFER_SIZE = 10;
public void produce() {
while (true) {
synchronized (buffer) {
// 如果缓冲区已满,则生产者线程等待
while (buffer.size() == BUFFER_SIZE) {
try {
System.out.println("Buffer is full, producer is waiting...");
buffer.wait(); // 生产者释放锁并进入等待状态
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
// 缓冲区未满,生产数据并放入缓冲区
int data = generateData();
buffer.add(data);
System.out.println("Producer produced: " + data);
// 唤醒可能存在的等待的消费者线程
buffer.notify(); // 唤醒一个等待的线程
}
}
}
public void consume() {
while (true) {
synchronized (buffer) {
// 如果缓冲区为空,则消费者线程等待
while (buffer.isEmpty()) {
try {
System.out.println("Buffer is empty, consumer is waiting...");
buffer.wait(); // 消费者释放锁并进入等待状态
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
// 缓冲区非空,消费数据并移出缓冲区
int data = buffer.removeFirst();
System.out.println("Consumer consumed: " + data);
// 唤醒可能存在的等待的生产者线程
buffer.notify(); // 唤醒一个等待的线程
}
}
}
// 生成模拟数据的方法
private int generateData() {
return Math.abs(new Random().nextInt() % 100);
}
}
// 使用示例:
public class Main {
public static void main(String[] args) {
ProducerConsumer pc = new ProducerConsumer();
Thread producerThread = new Thread(pc::produce, "Producer");
Thread consumerThread = new Thread(pc::consume, "Consumer");
producerThread.start();
consumerThread.start();
}
}
在这个例子中:
- 我们创建了一个
ProducerConsumer
类,其中有一个可同步访问的缓冲区(LinkedList)。 - 生产者线程会在缓冲区满时调用
buffer.wait()
,释放对象锁并进入等待状态,直到被其他线程唤醒。 - 消费者线程则在缓冲区空时调用
buffer.wait()
进入等待。 - 当生产者向缓冲区添加数据后,会调用
buffer.notify()
唤醒一个等待的消费者线程。 - 反过来,当消费者从缓冲区取出数据后,也会调用
buffer.notify()
唤醒可能等待的生产者线程。
这样,通过 synchronized
和 wait()
、notify()
方法的配合使用,实现了生产者和消费者线程之间的同步和通信。