📅  最后修改于: 2023-12-03 15:21:39.492000             🧑  作者: Mango
在多线程编程中,生产者消费者问题是一个经典问题。该问题描述了两类线程,生产者线程和消费者线程,在同一个共享缓冲区上运行。生产者不断地往缓冲区中生产数据,消费者不断地从缓冲区中取出数据,直到缓冲区为空或者满了。这个过程需要保证生产者和消费者交替运行,避免数据互相干扰。
在Java中,可以通过等待唤醒机制来解决生产者消费者问题。具体的实现步骤如下:
定义共享的缓冲区,包括缓冲区的大小和数据结构。
定义生产者线程和消费者线程,分别对缓冲区进行生产和消费操作。
在生产者线程中,使用synchronized关键字对共享的缓冲区进行加锁,然后进行生产操作。如果缓冲区已满,则调用wait()方法等待消费者取走数据。
在消费者线程中,使用synchronized关键字对共享的缓冲区进行加锁,然后进行消费操作。如果缓冲区为空,则调用wait()方法等待生产者产生数据。
当生产者产生数据时,调用notify()方法唤醒等待的消费者线程。当消费者取走数据时,调用notify()方法唤醒等待的生产者线程。
下面是一个示例代码:
public class ProducerConsumer {
private static final int CAPACITY = 10;
private static Queue<Integer> queue = new LinkedList<>();
private static Random random = new Random();
public static void main(String[] args) {
Thread producerThread = new Thread(new Producer());
Thread consumerThread = new Thread(new Consumer());
producerThread.start();
consumerThread.start();
}
static class Producer implements Runnable {
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.size() == CAPACITY) {
try {
System.out.println("Queue is full, waiting for consumer...");
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int num = random.nextInt(100);
queue.offer(num);
System.out.println("Produced: " + num);
queue.notifyAll();
}
}
}
}
static class Consumer implements Runnable {
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
try {
System.out.println("Queue is empty, waiting for producer...");
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Consumed: " + queue.poll());
queue.notifyAll();
}
}
}
}
}
在这个示例代码中,我们定义了一个队列queue作为共享的缓冲区。生产者线程不断产生数据并放入队列中,如果队列已满,则等待消费者线程取走数据。消费者线程不断从队列中取出数据并消费,如果队列为空,则等待生产者线程产生数据。
在生产者线程中,我们使用了while循环来判断队列是否已满,如果已满则调用wait()方法等待消费者线程的唤醒信号。在消费者线程中,我们也使用了while循环来判断队列是否为空,如果为空则调用wait()方法等待生产者线程的唤醒信号。
当生产者线程产生数据时,调用queue.notifyAll()方法唤醒等待的消费者线程;当消费者线程取走数据时,调用queue.notifyAll()方法唤醒等待的生产者线程。
这样,我们就实现了一个简单的生产者消费者模型。适当地使用阻塞、唤醒机制,可以有效地实现多线程之间的协作。