Java使用阻塞队列BlockingQueue实现生产者消费者的方法

 更新时间:2024年11月11日 14:11:06   作者:麦田  
BlockingQueue是一个支持阻塞插入和移除操作的队列,常用于多线程环境下的生产者和消费者场景,文章介绍了阻塞队列BlockingQueue的概念和其在生产者消费者模式中的应用,提供了一个简单的示例,展示了如何使用ArrayBlockingQueue来实现生产者消费者模式

什么是阻塞队列

阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除方法。

  • 1、支持阻塞的插入方法:意思是当队列满时,队列会阻塞插入元素的线程,直到队列不满。
  • 2、支持阻塞的移除方法:意思是在队列为空时,获取元素的线程会等待队列变为非空。

阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者是从队列里取元素的线程。 阻塞队列就是生产者用来存放元素、消费者用来获取元素的容器。

Java中提供了几个对BlockingQueue的实现类,如: ArrayBlockingQueue, LinkedBlockingQueue, PriorityBlockingQueue, SynchronousQueue 等

在处理生产者/消费者问题上 我们将会使用ArrayBlockingQueue来实现,如下是我们需知道的重要方法:

  • put(E e): 这个方法用于向队列中插入元素,如果队列已满,需要等待可用的这间。
  • E take(): 这个方法用于从队列头部获取或者移除元素,如果队列为空则需要等待可用的元素。

使用BlockingQueue来解决生产者/消费者 示例

Mantou类

Producer产生的普通Java对象,并添加到队列中。

/**
 * Producer产生的馒头类
 * @author itmyhome
 *
 */
public class Mantou {
    private String mantou;
    public Mantou(String mantou) {
        this.mantou = mantou;
    }
    public String getMantou() {
        return mantou;
    }
    public void setMantou(String mantou) {
        this.mantou = mantou;
    }
}

Producer生产者类

Producer这个类会产生消息并将其放入队列中。

import java.util.concurrent.BlockingQueue;
public class Producer implements Runnable {
    BlockingQueue<Mantou> queue;
    public Producer(BlockingQueue<Mantou> queue) {
        this.queue = queue;
    }
    @Override
    public void run() {
        // 生产馒头
        for (int i = 0; i < 100; i++) {
            Mantou mt = new Mantou("" + i);
            try {
                Thread.sleep(100);
                queue.put(mt);
                System.out.println("生产馒头: " + mt.getMantou());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 添加退出消息
        Mantou msg = new Mantou("exit");
        try {
            queue.put(msg);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Consumer消费者类

Consumer类会从队列获取消息进行处理。如果获取的是退出消息则结束。

import java.util.concurrent.BlockingQueue;
public class Consumer implements Runnable {
    BlockingQueue<Mantou> queue;
    public Consumer(BlockingQueue<Mantou> queue) {
        this.queue = queue;
    }
    @Override
    public void run() {
        try {
            Mantou mantou;
            // 获取并处理消息直到接收到“exit”消息
            while (!(mantou = queue.take()).getMantou().equals("exit")) {
                Thread.sleep(100);
                System.out.println("消费馒头: " + mantou.getMantou());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

ProducerConsumerService

生产者/消费者的服务类将会产生固定大小的BlockingQueue,生产者和消费者同时共享该BlockingQueue,该服务类会起启动生产者和消费者线程。

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
 * @author itmyhome
 *
 */
public class ProducerConsumerService {
    public static void main(String[] args) {
        // 创建大小为10的 BlockingQueue
        BlockingQueue<Mantou> queue = new ArrayBlockingQueue<Mantou>(10);
        Producer producer = new Producer(queue);
        Consumer consumer = new Consumer(queue);
        // 开启 producer线程向队列中生产消息
        new Thread(producer).start();
        //开启 consumer线程 中队列中消费消息
        new Thread(consumer).start();
        System.out.println("Producer and Consumer has been started");
    }
}

程序运行结果:

Producer and Consumer has been started
生产馒头: 0
生产馒头: 1
消费馒头: 0
消费馒头: 1
生产馒头: 2
消费馒头: 2
生产馒头: 3
消费馒头: 3
生产馒头: 4
消费馒头: 4
生产馒头: 5
消费馒头: 5
生产馒头: 6
消费馒头: 6
......

参考资料

[1]: Java并发编程的艺术
[2]http://www.cnblogs.com/tonyspark/p/3722013.html

到此这篇关于Java使用阻塞队列BlockingQueue实现生产者消费者的文章就介绍到这了,更多相关Java生产者消费者内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MybatisPlus中@EnumValue注解使用及应用场景

    MybatisPlus中@EnumValue注解使用及应用场景

    @EnumValue注解标记在枚举类型的字段上,表示该字段是枚举值在数据库中存储的实际值,这对于枚举的持久化是关键,确保枚举在数据库中的表示与Java枚举类的一致性,下面就来详细的介绍一下@EnumValue注解如何使用,感兴趣的可以了解一下
    2025-10-10
  • 一篇文章带你入门Springboot整合微信登录与微信支付(附源码)

    一篇文章带你入门Springboot整合微信登录与微信支付(附源码)

    微信支付是腾讯公司的支付业务品牌,微信支付商户平台支持线下场所、公众号、小程序、PC网站、APP、企业微信等经营场景快速接入微信支付。这里一篇文章带你入门!
    2021-06-06
  • Java设计模式之单例模式示例详解

    Java设计模式之单例模式示例详解

    单例模式是最简单也是最基础的设计模式之一,单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。本文将通过一些示例代码为大家详细介绍一下单例模式,感兴趣的可以了解一下
    2021-12-12
  • Springboot非分布式定时任务实现代码

    Springboot非分布式定时任务实现代码

    这篇文章主要介绍了Springboot非分布式定时任务实现代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • springboot扫码登录的简单实现

    springboot扫码登录的简单实现

    本文主要介绍基于SpringBoot + Vue + Android实现的扫码登录,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • SpringBoot整合ShedLock解决定时任务防止重复执行的问题

    SpringBoot整合ShedLock解决定时任务防止重复执行的问题

    ShedLock是一个用于分布式系统中防止定时任务重复执行的库,本文主要介绍了SpringBoot整合ShedLock解决定时任务防止重复执行的问题,具有一定的参考价值,感兴趣的可以了解一下
    2025-01-01
  • 现代高效的java构建工具gradle的快速入门

    现代高效的java构建工具gradle的快速入门

    和Maven一样,Gradle只是提供了构建项目的一个框架,真正起作用的是Plugin,本文主要介绍了gradle入门,文中通过示例代码介绍的非常详细,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • idea打不开双击IDEA图标没反应的快速解决方案

    idea打不开双击IDEA图标没反应的快速解决方案

    这篇文章主要介绍了idea打不开双击IDEA图标没反应的快速解决方案,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • MyBatis使用Zookeeper保存数据库的配置可动态刷新的实现代码

    MyBatis使用Zookeeper保存数据库的配置可动态刷新的实现代码

    这篇文章主要介绍了MyBatis使用Zookeeper保存数据库的配置,可动态刷新,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-08-08
  • java执行Linux命令的方法

    java执行Linux命令的方法

    这篇文章主要介绍了java执行Linux命令的方法,涉及对Java中Runtime.exec()函数的应用,具有一定的参考借鉴价值,需要的朋友可以参考下
    2014-11-11

最新评论