【JAVA】经典的生产者-消费者

序言

闲来无事,记录学习历程,交个朋友。欢迎讨论碰撞,产生好的解决方案!!!👏👏👏

背景

记录一下生产者-消费者模型代码

代码

java 复制代码
package com.gyg.thread.demo2;
import java.util.LinkedList;
import java.util.Queue;

public class ProducerConsumerExample {
    public static void main(String[] args) {
        Buffer buffer = new Buffer(5); // 缓冲区大小为5

        // 创建生产者线程
        Thread producerThread = new Thread(new Producer(buffer));

        // 创建消费者线程
        Thread consumerThread = new Thread(new Consumer(buffer));

        // 启动线程
        producerThread.start();
        consumerThread.start();
    }
}

// 共享缓冲区
class Buffer {
    private Queue<Integer> queue = new LinkedList<>();
    private int capacity;

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

    // 生产方法
    public synchronized void produce(int value) throws InterruptedException {
        // 如果缓冲区已满,生产者等待
        while (queue.size() == capacity) {
            System.out.println("缓冲区已满,生产者等待...");
            wait();
        }

        // 生产数据
        queue.offer(value);
        System.out.println("生产者生产: " + value + ",缓冲区大小: " + queue.size());

        // 通知消费者可以消费了
        notifyAll();
    }

    // 消费方法
    public synchronized int consume() throws InterruptedException {
        // 如果缓冲区为空,消费者等待
        while (queue.isEmpty()) {
            System.out.println("缓冲区为空,消费者等待...");
            wait();
        }

        // 消费数据
        int value = queue.poll();
        System.out.println("消费者消费: " + value + ",缓冲区大小: " + queue.size());

        // 通知生产者可以生产了
        notifyAll();

        return value;
    }
}

// 生产者
class Producer implements Runnable {
    private Buffer buffer;

    public Producer(Buffer buffer) {
        this.buffer = buffer;
    }

    @Override
    public void run() {
        try {
            int value = 0;
            while (true) {
                buffer.produce(value);
                value++;

                // 模拟生产时间
                Thread.sleep((int)(Math.random() * 1000));
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

// 消费者
class Consumer implements Runnable {
    private Buffer buffer;

    public Consumer(Buffer buffer) {
        this.buffer = buffer;
    }

    @Override
    public void run() {
        try {
            while (true) {
                buffer.consume();

                // 模拟消费时间
                Thread.sleep((int)(Math.random() * 1500));
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

关键点说明

共享缓冲区 (Buffer 类):

  • 使用 synchronized 关键字确保线程安全
  • 使用 wait() 使线程等待
  • 使用 notifyAll() 唤醒等待的线程

生产者线程 (Producer 类):

  • 不断生产数据并放入缓冲区
  • 当缓冲区满时自动等待
  • 生产后唤醒消费者

消费者线程 (Consumer 类):

  • 不断从缓冲区取出数据
  • 当缓冲区空时自动等待
  • 消费后唤醒生产者

注意事项:

  • 使用 while 循环检查条件而不是 if,防止虚假唤醒
  • 生产者和消费者都有随机的休眠时间,模拟实际处理时间
  • 缓冲区大小限制为5,当满时生产者会等待

尾声

如果解决有解决你的问题,点点赞,求个关注👍👍👍

安能催眉折腰事权贵,使我不得开心颜🤞🤞🤞,加油👏👏👏

相关推荐
苏琢玉1 小时前
从零开始做 Go 项目:我的目录设计分享
开发语言·后端·golang
郝学胜-神的一滴1 小时前
Linux信号的概念与机制
linux·服务器·开发语言·c++·程序人生
沐雨风栉1 小时前
被局域网困住的文件?cpolar让 Go File 随时随地能用
运维·服务器·开发语言·数据库·后端·缓存·golang
SamRol1 小时前
ThreadLocal、Sychronized和ReentrantLock
java
编程小Y1 小时前
C++ ODB ORM 从入门到实战应用
开发语言·c++
徐同保1 小时前
n8n项目node后端sqlite相关的
java·数据库·sqlite
r***99821 小时前
【JAVA进阶篇教学】第十一篇:Java中ReentrantLock锁讲解
java·开发语言
宠..1 小时前
创建标签控件
java·服务器·开发语言·前端·c++·qt
-大头.1 小时前
Spring Boot CLI 从入门到企业级实战(上下篇)
java·spring boot·后端