Java 实现生产者-消费者模式的 5 种方式

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

生产者-消费者模式是并发编程中的经典问题,用于解决线程间协作数据交换的需求。以下是 Java 中实现该模式的 5 种主流方式,从基础到高级逐步深入:


1. 使用 wait()notify()(最基础方式)

class Buffer {
    private Queue<Integer> queue = new LinkedList<>();
    private int capacity;

    public Buffer(int capacity) {
        this.capacity = capacity;
    }

    public synchronized void produce(int item) throws InterruptedException {
        while (queue.size() == capacity) {
            wait(); // 缓冲区满,生产者等待
        }
        queue.add(item);
        System.out.println("Produced: " + item);
        notifyAll(); // 唤醒消费者
    }

    public synchronized int consume() throws InterruptedException {
        while (queue.isEmpty()) {
            wait(); // 缓冲区空,消费者等待
        }
        int item = queue.poll();
        System.out.println("Consumed: " + item);
        notifyAll(); // 唤醒生产者
        return item;
    }
}

特点

  • 基于 Object 的监视器机制(synchronized + wait()/notify())。
  • 需要手动处理线程阻塞和唤醒。

2. 使用 BlockingQueue(推荐方式)

BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10); // 容量为10

// 生产者
Runnable producer = () -> {
    try {
        int item = (int) (Math.random() * 100);
        queue.put(item); // 队列满时自动阻塞
        System.out.println("Produced: " + item);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
};

// 消费者
Runnable consumer = () -> {
    try {
        int item = queue.take(); // 队列空时自动阻塞
        System.out.println("Consumed: " + item);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
};

// 启动线程
new Thread(producer).start();
new Thread(consumer).start();

特点

  • 直接利用 BlockingQueue 的线程安全特性(底层基于 ReentrantLock + Condition)。
  • 无需手动同步,代码简洁。

3. 使用 LockCondition(更灵活)

class BufferWithLock {
    private final Lock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();
    private Queue<Integer> queue = new LinkedList<>();
    private int capacity;

    public BufferWithLock(int capacity) {
        this.capacity = capacity;
    }

    public void produce(int item) throws InterruptedException {
        lock.lock();
        try {
            while (queue.size() == capacity) {
                notFull.await(); // 等待"非满"条件
            }
            queue.add(item);
            notEmpty.signal(); // 唤醒一个消费者
        } finally {
            lock.unlock();
        }
    }

    public int consume() throws InterruptedException {
        lock.lock();
        try {
            while (queue.isEmpty()) {
                notEmpty.await(); // 等待"非空"条件
            }
            int item = queue.poll();
            notFull.signal(); // 唤醒一个生产者
            return item;
        } finally {
            lock.unlock();
        }
    }
}

特点

  • 更细粒度的控制(可区分“非空”和“非满”条件)。
  • 支持公平锁、可中断等高级特性。

4. 使用 Semaphore(信号量控制)

class BufferWithSemaphore {
    private Queue<Integer> queue = new LinkedList<>();
    private Semaphore emptySlots;
    private Semaphore filledSlots;
    private Semaphore mutex;

    public BufferWithSemaphore(int capacity) {
        emptySlots = new Semaphore(capacity); // 初始空闲容量
        filledSlots = new Semaphore(0);      // 初始已填充容量
        mutex = new Semaphore(1);            // 互斥锁
    }

    public void produce(int item) throws InterruptedException {
        emptySlots.acquire(); // 获取空闲槽位
        mutex.acquire();      // 互斥访问队列
        queue.add(item);
        mutex.release();
        filledSlots.release(); // 增加已填充槽位
    }

    public int consume() throws InterruptedException {
        filledSlots.acquire(); // 获取已填充槽位
        mutex.acquire();
        int item = queue.poll();
        mutex.release();
        emptySlots.release();  // 释放空闲槽位
        return item;
    }
}

特点

  • 通过信号量直接控制资源数量。
  • 适合复杂资源分配场景。

5. 使用 Exchanger(单生产者单消费者交换)

Exchanger<String> exchanger = new Exchanger<>();

// 生产者
Runnable producer = () -> {
    try {
        String data = "Produced Data";
        System.out.println("Producer sends: " + data);
        data = exchanger.exchange(data); // 阻塞直到消费者交换数据
        System.out.println("Producer received: " + data);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
};

// 消费者
Runnable consumer = () -> {
    try {
        String data = exchanger.exchange(null); // 阻塞直到生产者发送数据
        System.out.println("Consumer received: " + data);
        data = "Consumed Data";
        exchanger.exchange(data); // 返回处理后的数据
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
};

new Thread(producer).start();
new Thread(consumer).start();

特点

  • 适用于严格交替执行的生产者-消费者模型。
  • 每次只能交换一个数据项。

对比总结

实现方式适用场景优点缺点
wait()/notify()传统同步场景无需额外依赖需手动处理条件判断
BlockingQueue大多数标准场景(推荐)代码简洁,线程安全灵活性较低
Lock + Condition需要精细控制的场景支持多个条件队列代码稍复杂
Semaphore资源数量固定的场景(如连接池)直观控制资源需额外互斥锁
Exchanger单对单严格交替场景无需缓冲区仅限一对一通信

最佳实践建议

  1. 优先选择 BlockingQueue:适用于 90% 的标准场景。
  2. 需要超时控制时用 Lock + Condition:例如 await(timeout, unit)
  3. 避免 wait()/notify() 的误用:容易导致死锁或虚假唤醒。

通过合理选择实现方式,可以高效解决生产者-消费者问题!

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦幻南瓜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值