Java多线程生产者消费者模式实战

Elena
Elena
发布时间:2026-10-13| 6人浏览过
原创

本文利用Java多线程技术,以“子弹填入枪膛”为场景,详细解析如何通过内置锁(synchronized)、wait() 和 notify() 方法实现生产者与消费者的线程同步。该方案旨在防止缓冲区溢出或为空时引发的错误操作,确保线程安全交互。

问题分析:线程同步的核心

生产者-消费者问题要求两个线程协同工作:一个负责向共享缓冲区放入数据,另一个负责取出。核心难点在于同步控制:

  • 当缓冲区已满时,生产者必须暂停生产并等待,直到消费者取走空间;
  • 当缓冲区为空时,消费者必须暂停等待,直到生产者放入数据。

在 Java 中,最简单且基础的实现方式是使用对象锁的 wait() 和 notify() 机制。wait() 会使当前线程释放锁并进入休眠,notify() 则随机唤醒一个处于等待状态的线程,使其重新竞争锁。

第1步:定义共享缓冲区(枪膛)

首先需要创建一个代表缓冲区的类 GunClip。该类持有用于存放数据的列表,并利用布尔值 bFull 标记状态。

  • 目的:统一管理资源访问,提供安全的放入和获取接口。
  • 关键设计:所有读写操作必须包裹在 synchronized 块中,保证同一时刻只有一个线程能修改状态。

class GunClip {
    private List<Integer> list = new ArrayList<>();
    // 标记是否满了,true表示已满,false表示已空
    private boolean bFull = false;

    // 生产者调用此方法放入子弹
    public synchronized void put(List<Integer> bullets) {
        // 如果已满,生产者直接等待
        if (bFull) {
            try {
                wait();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        // 执行放入操作
        this.list = bullets;
        bFull = true;
        System.out.println("\n机枪开始压入子弹:" + "\n");
        for (int j = 0; j < list.size(); j++) {
            System.out.println("已压入第" + (j + 1) + "颗子弹");
        }
        
        // 放入完成后通知等待的消费者
        notify();
    }

    // 消费者调用此方法取出子弹
    public synchronized void get() {
        // 如果为空,消费者直接等待
        if (!bFull) {
            try {
                wait();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        // 执行取出操作
        System.out.println("\n机枪开始射出子弹:" + "\n");
        for (int i = list.size(); i > 0; i--) {
            int j = list.get(i - 1);
            System.out.println("已射出第" + j + "颗子弹");
        }
        
        // 清空并重置状态,通知等待的生产者
        bFull = false;
        notify();
    }
}

第2步:实现生产者线程

生产者负责模拟连续装入子弹的过程。它持有对缓冲区 GunClip 的引用,循环创建新的子弹列表并调用缓冲区的 put 方法。


class Producer extends Thread {
    private GunClip clip;
    private List<Integer> list;

    Producer(GunClip clip) {
        this.clip = clip;
    }

    @Override
    public void run() {
        // 循环生产3轮
        for (int i = 0; i < 3; i++) {
            list = new ArrayList<>();
            // 假设每个弹夹容量为12
            for (int j = 0; j < 12; j++) {
                list.add(j + 1);
            }
            clip.put(list);
        }
    }
}

第3步:实现消费者线程

消费者线程需要不断从缓冲区获取数据。为了演示持续的效果,此处使用 while(true) 死循环调用 get 方法。在实际业务逻辑中,应包含退出机制。


class Consumer extends Thread {
    private GunClip clip;

    Consumer(GunClip clip) {
        this.clip = clip;
    }

    @Override
    public void run() {
        while (true) {
            clip.get();
        }
    }
}

第4步:启动测试入口

在主程序中实例化上述类并启动线程。注意类名中的拼写修正:Concumer 应更正为 Consumer,以免引起误解。


public class TestGun {
    public static void main(String[] args) {
        GunClip clip = new GunClip();
        Producer p = new Producer(clip);
        Consumer c = new Consumer(clip);
        p.start();
        c.start();
    }
}

完成判断与注意事项

运行上述代码后,控制台将交替输出“机枪开始压入子弹”和“机枪开始射出子弹”的信息。这表明 wait() 和 notify() 已生效,线程在缓冲区满/空时正确挂起,并在条件满足后被唤醒。

在实际开发中,处理多线程同步还需注意以下几点:

  1. 伪唤醒(Spurious Wakeups):wait() 可能在没有收到 notify 的情况下返回,因此最佳实践是在 if 语句外使用 while 循环检查状态条件。
  2. 中断异常:捕获 InterruptedException 时应妥善处理,通常通过恢复中断状态来保留上游线程的中断信息。
  3. 锁的粒度:对于复杂的并发需求,推荐使用 java.util.concurrent 包下的 BlockingQueue 或 ReentrantLock 以获得更灵活的控制。
以上就是Java多线程解决生产者消费者问题的详细内容,更多关于Java并发编程的资料请关注本站其它相关文章!
相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。