Java面试题之多线程 如何写代码来解决生产者消费者问题?
生产者消费者问题是一个经典的多线程问题,涉及到两个线程:生产者和消费者。生产者负责生成数据并将其放入缓冲区,而消费者则从缓冲区中取出数据进行处理。为了避免缓冲区溢出和空消费,需要使用适当的同步机制。
下面是一个使用Java的wait()
和notify()
方法来解决生产者消费者问题的示例代码:
import java.util.LinkedList;
import java.util.Queue;
class ProducerConsumer {
private final Queue<Integer> queue = new LinkedList<>();
private final int LIMIT = 10; // 缓冲区的大小
private final Object lock = new Object(); // 锁对象
// 生产者
public void produce() throws InterruptedException {
int value = 0;
while (true) {
synchronized (lock) {
// 如果缓冲区满,等待消费者消费
while (queue.size() == LIMIT) {
lock.wait();
}
// 生产数据
queue.add(value);
System.out.println("Produced: " + value);
value++;
// 通知消费者可以消费
lock.notifyAll();
}
Thread.sleep(1000); // 模拟生产时间
}
}
// 消费者
public void consume() throws InterruptedException {
while (true) {
synchronized (lock) {
// 如果缓冲区空,等待生产者生产
while (queue.isEmpty()) {
lock.wait();
}
// 消费数据
int value = queue.poll();
System.out.println("Consumed: " + value);
// 通知生产者可以生产
lock.notifyAll();
}
Thread.sleep(1000); // 模拟消费时间
}
}
public static void main(String[] args) {
ProducerConsumer pc = new ProducerConsumer();
Thread producerThread = new Thread(() -> {
try {
pc.produce();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
Thread consumerThread = new Thread(() -> {
try {
pc.consume();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
producerThread.start();
consumerThread.start();
}
}
Queue<Integer>
来作为缓冲区,限制其大小为LIMIT
。Object
作为锁,确保对缓冲区的访问是线程安全的。synchronized
块来获取锁。lock.wait()
使生产者线程等待。lock.notifyAll()
通知消费者线程。synchronized
块来获取锁。lock.wait()
使消费者线程等待。lock.notifyAll()
通知生产者线程。wait()
和notifyAll()
时,必须在synchronized
块中调用。