生产者-消费者问题是经典的多线程同步问题,可以使用 Java 中的 wait()
和 notify()
或者 notifyAll()
方法来实现。下面是一个简单的示例代码,演示了如何使用 wait()
和 notify()
方法来解决生产者-消费者问题:
import java.util.LinkedList;
import java.util.Queue;
public class ProducerConsumerExample {
public static void main(String[] args) {
final int CAPACITY = 5;
Queue<Integer> queue = new LinkedList<>();
Thread producer = new Thread(new Producer(queue, CAPACITY), "Producer");
Thread consumer = new Thread(new Consumer(queue), "Consumer");
producer.start();
consumer.start();
}
static class Producer implements Runnable {
private final Queue<Integer> queue;
private final int capacity;
public Producer(Queue<Integer> queue, int capacity) {
this.queue = queue;
this.capacity = capacity;
}
@Override
public void run() {
int value = 0;
while (true) {
synchronized (queue) {
try {
while (queue.size() == capacity) {
System.out.println("Queue is full, Producer is waiting...");
queue.wait();
}
System.out.println("Producer produced: " + value);
queue.offer(value++);
queue.notifyAll();
Thread.sleep(1000); // 模拟生产过程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
static class Consumer implements Runnable {
private final Queue<Integer> queue;
public Consumer(Queue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
try {
while (queue.isEmpty()) {
System.out.println("Queue is empty, Consumer is waiting...");
queue.wait();
}
int value = queue.poll();
System.out.println("Consumer consumed: " + value);
queue.notifyAll();
Thread.sleep(1500); // 模拟消费过程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
解释说明:
-
Queue 定义: 使用
LinkedList
实现Queue
,用于存储生产者和消费者共享的数据。 -
Producer 类:
run()
方法中使用synchronized
关键字锁住queue
对象,确保多个生产者线程互斥访问。- 如果队列满了 (
queue.size() == capacity
),则生产者线程调用queue.wait()
进入等待状态,直到消费者消费数据并唤醒生产者。 - 生产者生产数据 (
queue.offer(value++)
),并使用queue.notifyAll()
唤醒所有等待的消费者线程。
-
Consumer 类:
run()
方法中同样使用synchronized
关键字锁住queue
对象。- 如果队列为空 (
queue.isEmpty()
),则消费者线程调用queue.wait()
进入等待状态,直到生产者生产数据并唤醒消费者。 - 消费者消费数据 (
queue.poll()
),并使用queue.notifyAll()
唤醒所有等待的生产者线程。
-
注意事项:
- 使用
wait()
和notify()
方法时,必须在同步代码块中使用,并且必须持有对象的锁(即使用synchronized
)。 notify()
方法唤醒一个等待的线程,而notifyAll()
方法唤醒所有等待的线程,具体使用哪个取决于需求。- 生产者和消费者通过共享的队列来进行数据交换,通过
wait()
和notify()
方法来进行线程间的通信和同步。
- 使用
以上代码演示了基本的生产者-消费者模型的实现方式,可以根据具体的需求和场景进行适当调整和扩展。