📜  了解生产者消费者问题上的线程Java(1)

📅  最后修改于: 2023-12-03 15:21:39.492000             🧑  作者: Mango

了解生产者消费者问题上的线程Java

在多线程编程中,生产者消费者问题是一个经典问题。该问题描述了两类线程,生产者线程和消费者线程,在同一个共享缓冲区上运行。生产者不断地往缓冲区中生产数据,消费者不断地从缓冲区中取出数据,直到缓冲区为空或者满了。这个过程需要保证生产者和消费者交替运行,避免数据互相干扰。

在Java中,可以通过等待唤醒机制来解决生产者消费者问题。具体的实现步骤如下:

  1. 定义共享的缓冲区,包括缓冲区的大小和数据结构。

  2. 定义生产者线程和消费者线程,分别对缓冲区进行生产和消费操作。

  3. 在生产者线程中,使用synchronized关键字对共享的缓冲区进行加锁,然后进行生产操作。如果缓冲区已满,则调用wait()方法等待消费者取走数据。

  4. 在消费者线程中,使用synchronized关键字对共享的缓冲区进行加锁,然后进行消费操作。如果缓冲区为空,则调用wait()方法等待生产者产生数据。

  5. 当生产者产生数据时,调用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()方法唤醒等待的生产者线程。

这样,我们就实现了一个简单的生产者消费者模型。适当地使用阻塞、唤醒机制,可以有效地实现多线程之间的协作。