阻塞队列以及阻塞队列的一个使用
阻塞队列以及阻塞队列的一个使用
阻塞队列简介
阻塞队列(Blocking Queue)是一种常见的队列数据结构,它具有特殊的行为,可以用于多线程编程中,以协调不同线程之间的任务执行和数据传递。阻塞队列在多线程环境中非常有用,因为它可以安全地在队列为空或已满时进行线程的阻塞或唤醒操作。
阻塞队列的主要特点包括:
-
队列操作的线程安全性:阻塞队列提供了线程安全的队列操作,多个线程可以同时向队列中添加元素或者从队列中取出元素,而不会导致数据不一致或竞态条件的问题。
-
阻塞操作:当队列为空时,试图从队列中取出元素的线程会被阻塞,直到队列中有可用元素。当队列已满时,试图向队列中添加元素的线程也会被阻塞,直到队列有空间容纳新元素。
-
队列的大小限制:阻塞队列通常具有一个最大容量,当队列达到最大容量时,试图向队列中添加元素的线程会被阻塞。
阻塞队列的使用场景包括多线程生产者-消费者问题、线程池任务管理、事件驱动编程等,它们可以帮助有效地协调线程之间的工作,提高多线程程序的效率和可维护性。
Java中的java.util.concurrent
包提供了一些常见的阻塞队列实现,如LinkedBlockingQueue
和ArrayBlockingQueue
等。其他编程语言和库中也有类似的实现,用于支持多线程编程。
阻塞队列的应用
阻塞队列在多线程编程中有广泛的应用,特别是在以下方面:
-
生产者-消费者问题:阻塞队列常用于解决生产者-消费者问题,其中生产者线程将数据放入队列,而消费者线程从队列中取出数据。阻塞队列可以有效地协调这两种操作,确保生产者和消费者之间的同步和数据的安全传递。
-
线程池任务管理:线程池中的任务队列通常是一个阻塞队列,等待执行的任务会被放入队列中,线程池中的工作线程从队列中取出任务并执行。这种方式可以控制同时执行的任务数量,以防止资源过度消耗。
-
事件驱动编程:在事件驱动编程中,事件生产者将事件放入队列,而事件消费者从队列中取出事件并响应。这种模型可以在多线程环境中实现,阻塞队列用于传递事件数据。
在Java中,你可以使用java.util.concurrent
包提供的阻塞队列来方便地实现这些场景。以下是一个具体的Java示例,演示了如何使用LinkedBlockingQueue
来实现一个生产者-消费者模型:
import java.util.concurrent.*;public class BlockingQueueExample {public static void main(String[] args) {// 创建一个容量为10的阻塞队列BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10);// 创建生产者线程Thread producer = new Thread(() -> {try {for (int i = 1; i <= 10; i++) {System.out.println("Producing: " + i);queue.put(i); // 将数据放入队列Thread.sleep(1000); // 模拟生产过程}} catch (InterruptedException e) {e.printStackTrace();}});// 创建消费者线程Thread consumer = new Thread(() -> {try {for (int i = 1; i <= 10; i++) {int value = queue.take(); // 从队列中取出数据System.out.println("Consuming: " + value);Thread.sleep(1500); // 模拟消费过程}} catch (InterruptedException e) {e.printStackTrace();}});// 启动生产者和消费者线程producer.start();consumer.start();}
}
在这个示例中,生产者线程不断地向阻塞队列中放入数据,而消费者线程不断地从队列中取出数据,它们之间通过阻塞队列实现了同步。这个例子演示了阻塞队列在生产者-消费者问题中的应用。
阻塞队列Springboot实现案例之线程池任务管理
有这样一个场景,如果要频繁存数据,等待数据库的响应,这样需要很长的时间,但是如果流程逻辑正确的话我们可以先把结果返回给前端,然后在异步进行数据的存储。
执行逻辑
- 创建一个阻塞队列:你可以选择使用
java.util.concurrent
包中的阻塞队列,如LinkedBlockingQueue
,来存储要插入数据库的数据。也可以用ArrayBlockingQueue
当作阻塞队列。
private BlockingQueue<User> blockingQueue = new ArrayBlockingQueue<>(1024);
- 创建一个异步方法:在Spring中,你可以使用
@Async
注解来定义一个异步方法。这个方法将从阻塞队列中取出数据,并将数据插入数据库。
@Async
public void processQueue() {while (true) {try {User user = blockingQueue.take(); // 从队列中取出数据userService.save(user); // 插入数据库} catch (InterruptedException e) {Thread.currentThread().interrupt();break;}}
}
- 配置Spring异步支持:确保你的Spring应用程序启用了异步支持。你需要在配置类中添加
@EnableAsync
注解,并配置一个TaskExecutor
来执行异步方法。使用一个配置类
package com.xwhking.springboottemplate.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;@Configuration
@EnableAsync // 启用异步支持
public class AsyncThreadPoolConfig {@Beanpublic ThreadPoolTaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5); // 核心线程数executor.setMaxPoolSize(10); // 最大线程数executor.setQueueCapacity(25); // 队列容量executor.setThreadNamePrefix("MyAsyncThread-"); // 线程名称前缀executor.initialize(); // 初始化return executor;}@Beanpublic SimpleAsyncTaskExecutor simpleAsyncTaskExecutor() {return new SimpleAsyncTaskExecutor();}
}
- 编写Controller方法:在Controller中编写一个方法,该方法将数据放入阻塞队列。这个方法应该是同步的,因为它只是将数据放入队列,不会等待数据插入完成。
@GetMapping("/addUser")public BaseResponse<String> testBlockQueue(String username , String password, String nickname){User user = new User();user.setUsername(username);user.setPassword(password);user.setNickname(nickname);blockingQueue.offer(user);taskExecutor.execute(this::processQueue);return null;}
Controller完整代码
package com.xwhking.springboottemplate.controller;import com.xwhking.springboottemplate.common.BaseResponse;
import com.xwhking.springboottemplate.generator.domain.User;
import com.xwhking.springboottemplate.generator.service.UserService;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;@RestController
@RequestMapping("/blockQueue")
public class TestBlockQueueController {@Resourceprivate UserService userService;private BlockingQueue<User> blockingQueue = new ArrayBlockingQueue<>(1024);@ResourceTaskExecutor taskExecutor;@Asyncpublic void processQueue() {while (true) {try {User user = blockingQueue.take(); // 从队列中取出数据userService.save(user); // 插入数据库} catch (InterruptedException e) {Thread.currentThread().interrupt();break;}}}@GetMapping("/addUser")public BaseResponse<String> testBlockQueue(String username , String password, String nickname){User user = new User();user.setUsername(username);user.setPassword(password);user.setNickname(nickname);blockingQueue.offer(user);taskExecutor.execute(this::processQueue);return null;}
}
相关程序解释
taskExecutor.execute(this::processQueue);
相关解释
taskExecutor.execute(this::processQueue)
这行代码的意思是使用 taskExecutor
(一个 TaskExecutor
对象)来执行 this::processQueue
表达式。这个表达式实际上是 Java 8 引入的方法引用(Method Reference)的一种形式,表示对当前对象的 processQueue
方法的引用。
具体来说:
this
表示当前对象,即TestBlockQueueController
类的实例。processQueue
是TestBlockQueueController
类中定义的一个方法。
因此,this::processQueue
表达式表示对当前对象的 processQueue
方法的引用。
taskExecutor.execute(this::processQueue)
这行代码的目的是将 processQueue
方法的执行放入 taskExecutor
管理的线程池中异步执行。这可以确保 processQueue
方法在一个独立的线程中运行,而不会阻塞当前线程(通常是 HTTP 请求的线程),从而实现异步处理。
总结一下,taskExecutor.execute(this::processQueue)
的作用是将 processQueue
方法提交给线程池异步执行,而不是在当前线程中执行。这对于处理需要较长时间的任务或需要与其他任务并发执行的任务非常有用。
相关文章:

阻塞队列以及阻塞队列的一个使用
阻塞队列以及阻塞队列的一个使用 阻塞队列简介 阻塞队列(Blocking Queue)是一种常见的队列数据结构,它具有特殊的行为,可以用于多线程编程中,以协调不同线程之间的任务执行和数据传递。阻塞队列在多线程环境中非常有…...

kafka的请求处理机制
目录 前言: kafak是如何处理请求的? 控制请求与数据类请求 参考资料 前言: 无论是 Kafka 客户端还是 Broker 端,它们之间的交互都是通过“请求 / 响应”的方式完成的。比如,客户端会通过网络发送消息生产请求给 B…...

Linux系统管理:虚拟机Centos Stream 9安装
目录 一、理论 1.Centos Stream 9 二、实验 1.虚拟机Centos Stream 9安装准备阶段 2.安装Centos Stream 9 3.进入系统 一、理论 1.Centos Stream 9 (1) 简介 CentOS Stream 是一种 Linux 操作系统。安装此操作系统的难题在于,在安装此系统之前,…...

5种排序算法
文章目录 一,排序算法时间复杂度比较二,插入排序三,冒泡排序四,快速排序五,堆排序六,二分归并排序 一,排序算法时间复杂度比较 算法最坏情况下平均情况下插入排序O(n )O(n)冒泡排序O(n)O(n)快速…...

TCP/IP(七)TCP的连接管理(四)
一 全连接队列 nginx listen 参数backlog的意义 nginx配置文件中listen后面的backlog配置 ① TCP全连接队列概念 全连接队列: 也称 accept 队列 ② 查看应用程序的 TCP 全连接队列大小 实验1: ss 命令查看 LISTEN状态下 Recv-Q/Send-Q 含义附加:…...

LeetCode【84】柱状图中的最大矩形
题目: 思路: https://blog.csdn.net/qq_28468707/article/details/103682528 https://www.jianshu.com/p/2b9a36a548fa 清晰 代码: public int largestRectangleArea(int[] heights) {int[] heightadd new int[heights.length 1];for (i…...

C++:关于模拟实现vector和list中迭代器模块的理解
文章目录 list和vector的迭代器对比list的实现过程完整代码 本篇是关于vector和list的模拟实现中,关于迭代器模块的更进一步理解,以及在前文的基础上增加对于反向迭代器的实现和库函数的对比等 本篇是写于前面模拟实现的一段时间后,重新回头…...

HTML 笔记 表格
1 表格基本语法 tr:table row th:table head 2 表格属性 2.1 基本属性 表格的基本属性是指表格的行、列和单元格但并不是每个表格的单元格大小都是统一的,所以需要设计者通过一些属性参数来修改表格的样子,让它们可以更更多样…...

3.1 C/C++ 使用字符与指针
C/C语言是一种通用的编程语言,具有高效、灵活和可移植等特点。C语言主要用于系统编程,如操作系统、编译器、数据库等;C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统、图形用户界面、嵌入式系统等。…...

[代码学习]einsum详解
einsum详解 该函数用于对一组输入 Tensor 进行 Einstein 求和,该函数目前仅适用于paddle的动态图。 Einstein 求和是一种采用 Einstein 标记法描述的 Tensor 求和,输入单个或多个 Tensor,输出单个 Tensor。 paddle.einsum(equation, *opera…...

女性必看——“黄体破裂”到底有多可怕?
前几天的亚运会上发生了这样一件事: 雅思敏(化名)是一名国外皮划艇运动员,在亚运会上奋力完成皮划艇比赛后,突然开始 剧烈腹痛、面色苍白,大汗淋漓,经过进一步检查,确诊卵巢黄体破裂…...

colab切换目录的解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...

基于SSM的生活缴费系统的设计与实现
末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…...

【WebLogic】WebLogic 2023年7月补丁导致JVM崩溃的解决方案
受影响版本: Oracle WebLogic 12c(12.2.1.4.0)Oracle WebLogic 14c(14.1.1.0.0) 问题描述: Oracle官方在2023年7月发布的最新版本的OPatch(13.9.4.2.13)存在一个新出现的Bug&#…...

简单OpenSL ES学习
初识OpenSL ES OpenSL ESObjects和Interfaces 所有的Object在OpenSl里面我们拿到的都是一个SLObjectItf:SLObjectItf_创建引擎创建过程要设计得这么麻烦?(object的生命周期)这么多参数,参数类型这么多学习障碍太大&…...

Linux网络编程- struct packet_mreq setsockopt()
struct packet_mreq struct packet_mreq 是一个数据结构,用于 Linux 中的原始数据包套接字,当我们想改变套接字的行为以接收特定类型的数据包时,它与 setsockopt() 函数配合使用。 下面是 struct packet_mreq 的定义: struct p…...

C++学习day4
作业: 1> 思维导图 2> 整理代码 1. 拷贝赋值函数课上代码 //拷贝赋值函数课上代码 #include<iostream> using namespace std;//创建类 class Stu { private://私有的string name;int socer;int *age;//此处注意用到指针类型 public://共有的//无参构…...

从零学算法54
54.给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 螺旋遍历:从左上角开始,按照 向右、向下、向左、向上 的顺序 依次 提取元素,然后再进入内部一层重复相同的步骤,直到…...

Logback日志框架使用详解以及如何Springboot快速集成
Logback简介 日志系统是用于记录程序的运行过程中产生的运行信息、异常信息等,一般有8个级别,从低到高为All < Trace < Debug < Info < Warn < Error < Fatal < OFF off 最高等级,用于关闭所有日志记录fatal 指出每个…...

Nginx概念
Nginx概念 Nginx 是一款面向性能设计的 HTTP 服务器,相较于 Apache、lighttpd 具有占有内存少,稳定性高等优势,同时也是一个非常高效的反向代理、负载平衡服务器 nginx使用的是反应器模式,主事件循环等待操作系统发出准备事件的信…...

vim基础指令(自用)
这个是自己随便写的,类似于笔记 vim 多模式编辑器 查看指令: gg: 定位光标到最开始行 shift(按)g 定位到最结尾行 nshift(按)g 定位到任意行 shift$ 定位到本行结尾 0 定位到本行开头 w:跨单词移动 h.j.k,l: 左下上右 …...

【centos7安装ElasticSearch】
概述 最近工作中有用到ES ,当然少不了自己装一个服务器捣鼓。本文的ElasticSearch 的版本: 7.17.3 一、下载 ElasticSearch 点此下载 下载完成后上传至 Linux 服务器,本文演示放在: /root/ 下,进行解压࿱…...

ElementPlus Switch 开关基础使用
昨天开发用到开关组件 后台返回字段是 can_write 默认是0 or 1 但是Switch 组件绑定的默认值默认是 true or false 直接绑定会导致默认是关闭状态 在页面一加载 值发生变化时 会自己调用 查了文档 需要使用 active-value 和 inactive-value 来指定绑定的数据类型 …...

Spring Boot:自定义注解--annotation
目录 自定义注解的定义和作用范围如何创建自定义注解创建注解接口 如何使用自定义注解进行数据验证创建注解处理器控制器中使用注解 如何为字段添加注解 自定义注解的定义和作用范围 自定义注解可以作用在类、方法、属性、参数、异常、字段或其他注解上。 如何创建自定义注解…...

WIFI频段
问题: 5ghzwifi频段带宽怎么选 智造喵回答: 选择5GHz WiFi频段的带宽取决于你的网络需求和设备兼容性。通常有两种可选的带宽:20MHz和40MHz。 20MHz带宽:这是较为常见的 WiFi 频段带宽设置。它提供较好的穿墙能力和信号稳定性…...

Java的引用详解与示例
引用的作用 在Java中,引用(Reference)是一种重要的概念,它们用于管理对象的生命周期、内存分配和垃圾回收。引用的作用包括以下几个方面: 内存管理:引用帮助Java虚拟机(JVM)管理内存…...

c++视觉处理---霍夫变换
霍夫直线变换的函数 HoughLines 是OpenCV库中用于执行霍夫直线变换的函数。霍夫直线变换用于检测图像中的直线。下面是该函数的基本用法: cv::HoughLines(image, lines, rho, theta, threshold);image: 输入的二值图像,通常是通过边缘检测算法生成的。…...

el-table 边框颜色修改 简单有效!
废话不多说,直接上图 (1)修改前的图如下: 以上是elementUI原组件自带的样式 (2)下面是修改后的边框图如下: 源码如下: <el-table :data"jctableData" border size…...

Zabbix第二部分:基于Proxy分布式部署实现Web监控和Zabbix HA集群的搭建
代理和高可用 一、基于zabbix-proxy的分布式监控1.1 分布式监控的作用1.2 数据流向1.3 构成组件 二、部署zabbix代理服务器Step1 前置准备Step2 设置 zabbix 的下载源,安装 zabbix-proxyStep3 部署数据库并将zabbix相关文件导入Step4 修改zabbix-proxy的配置文件&am…...

JumpServer rce深入剖析
影响范围 JumpServer < v2.6.2 JumpServer < v2.5.4 JumpServer < v2.4.5 JumpServer v1.5.9 修复链接及参考 修改了一处代码: Git History 增加了一处鉴权 def connect(self):user self.scope["user"]if user.is_authenticated and …...