java 中多线程、 队列使用实例,处理大数据业务
场景: 从redis 订阅数据 调用线程来异步处理数据
直接上代码
定义线程管理类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;import java.util.concurrent.*;/*** Created with IntelliJ IDEA.* @Description 线程池管理类*/
@Component
public class ThreadPoolManager implements BeanFactoryAware {private static Logger logger = LoggerFactory.getLogger(ThreadPoolManager.class);//用于从IOC里取对象private BeanFactory factory; //如果实现Runnable的类是通过spring的application.xml文件进行注入,可通过 factory.getBean()获取,这里只是提一下// 线程池维护线程的最少数量 (根据环境而定)private final static int CORE_POOL_SIZE = 10;// 线程池维护线程的最大数量 (根据环境而定)private final static int MAX_POOL_SIZE = 50;// 线程池维护线程所允许的空闲时间private final static int KEEP_ALIVE_TIME = 0;// 线程池所使用的缓冲队列大小 (此处队列设置 需要考虑处理数据的效率 内存的大小)private final static int WORK_QUEUE_SIZE = 99999;@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {factory = beanFactory;}// 消息队列public LinkedBlockingQueue<String> getMsgQueue() {return msgQueue;}LinkedBlockingQueue<String> msgQueue = new LinkedBlockingQueue<>();/*** 当线程池的容量满了,执行下面代码,将推送数据存入到缓冲队列*/final RejectedExecutionHandler handler = new RejectedExecutionHandler() {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {String temp = ((MsgHandleThread) r).getRecord();if (StringUtils.isEmpty(temp)) {msgQueue.offer(temp);}}};/*** 创建线程池*/final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, new ArrayBlockingQueue(WORK_QUEUE_SIZE), this.handler);/*** 将任务加入线程池---执行数据处理*/public void addPushRecord(String record) {MsgHandleThread subThread=new MsgHandleThread(record);threadPool.execute(subThread);}/*** 线程池的定时任务----> 称为(调度线程池)。此线程池支持 定时以及周期性执行任务的需求。*/final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5);/*** 检查(调度线程池),每秒执行一次,查看订单的缓冲队列是否有 订单记录,则重新加入到线程池*/final ScheduledFuture scheduledFuture = scheduler.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {//判断缓冲队列是否存在记录if (!msgQueue.isEmpty()) {//当线程池的队列容量少于WORK_QUEUE_SIZE,则开始把缓冲队列的订单 加入到 线程池if (threadPool.getQueue().size() < WORK_QUEUE_SIZE) {String record = msgQueue.poll();MsgHandleThread subThread=new MsgHandleThread(record);threadPool.execute(subThread);}}}}, 0, 1, TimeUnit.SECONDS);/*** 终止订单线程池+调度线程池*/public void shutdown() {//true表示如果定时任务在执行,立即中止,false则等待任务结束后再停止scheduledFuture.cancel(false);scheduler.shutdown();threadPool.shutdown();}
}
任务处理类
/*** Created with IntelliJ IDEA.* @Description 订阅数据 处理*/
@Component
@Scope("prototype")//spring 多例
public class MsgHandleThread implements Runnable {private Logger logger = LoggerFactory.getLogger(SubCheckDataThread.class);private IDataHandleService _serviceprivate String record;public SubCheckDataThread(String _record) {this.record = _record;}public String getRecord() {return record;}@Overridepublic void run() {try {if (StringUtils.isEmpty(this.record)) {return;}// 无法注入是采用此方法if (_service== null) {_service= ApplicationContextProvider.getBean(IDataHandleService .class);}//TODO 具体业务logger.info("消费完成",record);} catch (Exception e) {e.printStackTrace();}}
}
调用
import com.yicheng.common.properties.SetProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.ExecutorService;/*** <p>* 订阅redis消息* </p>** @Author: zhuYaqiang* @Date: 2024/06/12*/
@Component
public class SubscribeCheckData {@Autowiredprivate ThreadPoolManager threadPoolManager;/**** @Description: 查岗信息订阅---redis* @Param: [message]* @return: void* @Author: zhuYaqiang* @Date: 2024/06/12*/public void receiveMessage(String message) {try {threadPoolManager.addPushRecord(message);} catch (Exception e) {e.printStackTrace();}}}
redis 订阅消息后调用线程池处理数据
package com.yicheng.subscribeRedis;import com.yicheng.common.properties.SetProperties;
import com.yicheng.subscribeRedis.alarm.SubscribeAlarmNoticeData;
import com.yicheng.subscribeRedis.check.SubscribeCheckData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;/*** @title RedisSubscribeCHeck* @description* @create 2024/6/12 19:30*/
@Configuration
public class RedisMessageListener {@Autowiredprivate SetProperties setProperties;@BeanRedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,MessageListenerAdapter listenerCheckAdapter, MessageListenerAdapter listenerAlarmNoticeAdapter) {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(connectionFactory);listenerCheckAdapter.afterPropertiesSet();listenerAlarmNoticeAdapter.afterPropertiesSet();//订阅了的通道// 订阅查岗数据container.addMessageListener(listenerCheckAdapter, new PatternTopic(setProperties.getRedisCheckSub().getSubChannel()));//这个container 可以添加多个 messageListenerreturn container;}/*** 消息监听器适配器,绑定消息处理器,利用反射技术调用消息处理器的业务方法* 监听查岗消息* @param receiver* @return*/@BeanMessageListenerAdapter listenerCheckAdapter(SubscribeCheckData receiver) {return new MessageListenerAdapter(receiver, "receiveMessage");}/*** 消息监听器适配器,绑定消息处理器,利用反射技术调用消息处理器的业务方法* 监听报警通知信息* @param receiver* @return*/@BeanMessageListenerAdapter listenerAlarmNoticeAdapter(SubscribeAlarmNoticeData receiver) {return new MessageListenerAdapter(receiver, "receiveMessage");}}
以上代码已在实际项目中使用,觉得有用的点赞收藏评论
相关文章:
java 中多线程、 队列使用实例,处理大数据业务
场景: 从redis 订阅数据 调用线程来异步处理数据 直接上代码 定义线程管理类 import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org…...
13.图形程序接口(Graphics API)
**图形程序接口(Graphics API)**是计算机图形学中的一个重要概念,可以理解为“程序员与GPU之间的桥梁”。用通俗易懂的方式来解释: 通俗解释:图形API就像翻译官 想象你是一个老板(程序员)&…...
PPT自动化 python-pptx -7: 占位符(placeholder)
占位符(placeholder)是演示文稿中用于容纳内容的预格式化容器。它们通过让模板设计者定义格式选项,简化了创建视觉一致幻灯片的过程,同时让最终用户专注于添加内容。这加快了演示文稿的开发速度,并确保幻灯片之间的外观…...
Pyecharts之图表组合与布局优化
在数据可视化中,我们经常需要将多个图表组合在一起,以展示不同维度的数据或者进行对比分析。同时,合理的布局能够提升图表的可读性和用户体验。Pyecharts 提供了强大的组件和方法,让我们可以轻松实现图表的组合和布局优化。本篇将…...
流行的开源高性能数据同步工具 - Apache SeaTunnel 整体架构运行原理
概述 背景 数据集成在现代企业的数据治理和决策支持中扮演着至关重要的角色。随着数据源的多样化和数据量的迅速增长,企业需要具备强大的数据集成能力来高效地处理和分析数据。SeaTunnel通过其高度可扩展和灵活的架构,帮助企业快速实现多源数据的采集、…...
Android vendor.img中文件执行权问题
问题 Android 9、11往vendor.img增加文件,烧写到设备后发现增加的可执行文件没有执行权限。经过漫长查找,终于找到了问题的根源,谨以此篇献给哪些脚踏实地的人们。 根本原因 system/core/libcutils/fs_config.cpp文件,fs_confi…...
关于使用微服务的注意要点总结
一、防止过度设计 微服务的拆分一定要结合团队人员规模来考虑,笔者就曾遇到过一个公司的项目,是从外部采购回来的,微服务划分为十几个应用,我们在此项目基础上进行自行维护和扩展。由于公司业务规模不大,而且二次开发的…...
C++17 新增属性详解
文章目录 1. [[fallthrough]]用途示例应用场景 2. [[maybe_unused]]用途示例应用场景 3. [[nodiscard]]用途示例应用场景 总结 C17标准引入了多个新的属性(Attributes),这些属性为代码提供了更丰富的语义表达能力,同时帮助编译器生…...
使用python-docx包进行多文件word文字、字符批量替换
1、首先下载pycharm。 2、改为中文。 3、安装python-docx包。 搜索包名字,安装。 4、新建py文件,写程序。 from docx import Documentdef replace1(array1):# 替换词典(标签值按实际情况修改)dic {替换词1: array1[0], 替换…...
15_业务系统基类
创建脚本 SystemRoot.cs 因为 业务系统基类的子类 会涉及资源加载服务层ResSvc.cs 和 音乐播放服务层AudioSvc.cs 所以在业务系统基类 提取引用资源加载服务层ResSvc.cs 和 音乐播放服务层AudioSvc.cs 并调用单例初始化 using UnityEngine; // 功能 : 业务系统基类 public c…...
Pyecharts之散点图的视觉扩展
在数据可视化中,散点图是一种强大的工具,可用于展示数据点在二维平面上的分布情况。通过添加各种视觉组件,我们可以让散点图变得更加丰富和具有表现力,更能反映数据的多维度特征。本文将详细解读如何为散点图添加不同的视觉组件&a…...
Java学习教程,从入门到精通,JDBC删除数据库语法知识点(101)
一、JDBC删除数据库语法知识点 1. 概述 JDBC(Java Database Connectivity)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。 在JDBC中,删除数据库的操作主要是通过执行…...
Baklib如何推动企业知识管理的创新与转型探讨
内容概要 在当今快速发展的数字化时代,企业需要不断适应变化,以保持竞争优势。Baklib作为一款企业知识管理中台,扮演着推动数字化转型的重要角色。它通过提供一个集成的知识管理平台,帮助企业高效管理和共享内部及外部的知识资源…...
【算法】递归型枚举与回溯剪枝初识
递归型枚举与回溯剪枝初识 1.枚举子集2.组合型枚举3.枚举排列4.全排列问题 什么是搜索?搜索,是一种枚举,通过穷举所有的情况来找到最优解,或者统计合法解的个数。因此,搜索有时候也叫作暴搜。搜索一般分为深度优先搜索…...
无人机 PX4 飞控 | PX4源码添加自定义参数方法并用QGC显示与调整
无人机 PX4 飞控 | PX4源码添加自定义参数方法并用QGC显示与调整 0 前言 之前文章添加了一个自定义的模块,本篇文章在之前的自定义模块中,添加两个自定义参数 使用QGC显示出来,并通过QGC调整参数值,代码实现参数更新 新增的参…...
《CPython Internals》阅读笔记:p356-p359
《CPython Internals》学习第 19天,p356-p359 总结,总计 4 页。 一、技术总结 1.benchmark suite The benchmark suite is the tool to use when comparing the complete performance of Python. The Python Benchmark suite is a collection of Pyth…...
Linux--权限
Linux系统的权限管理是保障系统安全的重要机制,以下详细讲解权限相关概念及操作指令: 一、基础权限机制 1. 权限的三元组,读(r)、写(w)、执行(x) 每个文件或目录有三组…...
java后端之登录认证
基础登录功能:根据提供的用户名和密码判断是否存在于数据库 LoginController.java RestController Slf4j public class LoginController {Autowiredprivate UserService userService;PostMapping("/login")public Result login(RequestBody User user) {…...
【矩阵二分】力扣378. 有序矩阵中第 K 小的元素
给你一个 n x n 矩阵 matrix ,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。 请注意,它是 排序后 的第 k 小元素,而不是第 k 个 不同 的元素。 你必须找到一个内存复杂度优于 O(n2) 的解决方案。 示例 1࿱…...
C语言-构造数据类型
1、构造数据类型 结构体、共用体、枚举。 2、结构体 1、结构体的定义 结构体是一个自定义的复合数据类型,它允许将不同类型的数据组合在一起。 struct 结构体名 {数据类型1 成员变量1;数据类型2 成员变量2;数据类型3 成员变量3;数据类型4 成员变量4; } 2、结构体变…...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
