一个简单的生产者和消费者模型

2023-05-23 14:44:06 浏览数 (1)

一个简单的生产者和消费者模型

代码语言:javascript复制
import java.util.LinkedList;

public class ProducerConsumerExample {

    public static void main(String[] args) throws InterruptedException {
        final Buffer buffer = new Buffer(5); // 创建一个缓冲区,容量为5

        // 创建一个生产者线程
        Thread producerThread = new Thread(() -> {
            try {
                int value = 0;
                while (true) {
                    buffer.put(value  ); // 生产一个数据到缓冲区
                    Thread.sleep(1000); // 等待1秒钟
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 创建一个消费者线程
        Thread consumerThread = new Thread(() -> {
            try {
                while (true) {
                    int value = buffer.take(); // 从缓冲区中取出一个数据
                    System.out.println("Consumed: "   value);
                    Thread.sleep(2000); // 等待2秒钟
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 启动生产者和消费者线程
        producerThread.start();
        consumerThread.start();

        // 等待线程结束
        producerThread.join();
        consumerThread.join();
    }

    // 缓冲区类
    static class Buffer {
        private final LinkedList<Integer> queue; // 用链表实现缓冲区
        private final int capacity; // 缓冲区容量

        public Buffer(int capacity) {
            this.queue = new LinkedList<>();
            this.capacity = capacity;
        }

        // 生产一个数据
        public void put(int value) throws InterruptedException {
            synchronized (queue) {
                while (queue.size() == capacity) { // 缓冲区已满,等待消费者消费
                    queue.wait();
                }
                queue.add(value);
                queue.notifyAll(); // 通知消费者可以消费了
            }
        }

        // 消费一个数据
        public int take() throws InterruptedException {
            synchronized (queue) {
                while (queue.isEmpty()) { // 缓冲区为空,等待生产者生产
                    queue.wait();
                }
                int value = queue.remove();
                queue.notifyAll(); // 通知生产者可以生产了
                return value;
            }
        }
    }
}

我们常用的 LinkedList 就可以当队列使用,实现了Dequeue接口,还有 ConcurrentLinkedQueue,他们都属于非阻塞队列

说明

创建了一个缓冲区类Buffer,它使用一个链表来实现缓冲区,并且具有生产和消费两个方法put()和take()。在put()方法中,如果缓冲区已满,就等待消费者消费;否则,将数据加入缓冲区,并通知消费者可以消费了。在take()方法中,如果缓冲区为空,就等待生产者生产;否则,从缓冲区中取出一个数据,并通知生产者可以生产了。

在main()方法中创建了一个缓冲区对象,并创建了一个生产者线程和一个消费者线程。生产者线程不断地生产数据,并将其放入缓冲区中;消费者线程不断地从缓冲区中取出数据,并打印出来。我们通过调整生产者和消费者的等待时间,可以观察到生产者和消费者之间的交互过程。

扩展

在多线程中阻塞队列的使用非常常见,例如LinkedBlockingQueue中就使用的不是synchronized关键字,而是用的ReentrantLock,结合Condition来用的,此时了解synchronized和lock的区别也就有必要了

0 人点赞