springboot 多线程实战
先说下业务场景,业务1:基于实时轨迹数据打卡,业务2:基于非实时轨迹的时间差,计算累计时长。 简单点说就是从websocket获取到的实时数据,既要兼容不耗时操作,又要兼容耗时操作。
单线程做的话,一两个用户的数据没问题,用户多了就处理不过来。
实现思路是用TaskExecutor来做,一个task接收从redis lPop的数据,并放入BlockingQueue,另外的task从BlockingQueue获取数据。
@Autowiredprivate TaskExecutor taskExecutor1;@Autowiredprivate TaskExecutor taskExecutor2;@Autowiredprivate TaskExecutor taskExecutor3;static BlockingQueue<TrackHistory> dataQueue = new ArrayBlockingQueue<>(1 << 12);static BlockingQueue<TrackHistory> keepWatchQueue = new ArrayBlockingQueue<>(1 << 12);public static final String M = ":";@Bean("redisReadThread")public String service() {taskExecutor1.execute(() -> {while (true) {try {lPop();} catch (Exception e) {e.printStackTrace();}}});return null;}@Bean("calculationsBusinessData")public void calculationsService() {taskExecutor2.execute(() -> {while (true) {try {if (dataQueue.size() != 0) {TrackHistory trackRealTime = dataQueue.poll();if (trackRealTime == null) {Thread.sleep(100L);} else {//耗时方法doSomething();//存储当前日期+人员的最新位置坐标saveTrackToRedis(trackRealTime);}} else {Thread.sleep(100L);}} catch (Exception e) {log.error("业务1数据计算异常->{}", e.getMessage());}}});}@Bean("calculationsKeepWatch")public void keepWatchService() {taskExecutor3.execute(() -> {while (true) {try {if (keepWatchQueue.size() != 0) {TrackHistory trackRealTime = keepWatchQueue.poll();if (trackRealTime == null) {Thread.sleep(100L);} else {doSomething2(trackRealTime);}} else {Thread.sleep(100L);}} catch (Exception e) {log.error("业务2数据计算异常->{}", e.getMessage());}}});}/*** 从队列中读取数据** @return*/private synchronized void lPop() {Object o = redisTemplate.opsForList().leftPop(RedisKeyCons.COORDINATE);if (!org.springframework.util.StringUtils.isEmpty(o)) {TrackHistory trackRealTime = (TrackHistory) o;log.info("leftPop trackHistory = {}", trackRealTime);if (null != trackRealTime) {if (checkMemberExist(trackRealTime)) {return;}//存储当前日期+人员的最新位置坐标saveTrackToRedisForKeepWatch(trackRealTime);dataQueue.add(trackRealTime);keepWatchQueue.add(trackRealTime);}}}
配置线程池
/*** 线程池配置、启用异步***/
@EnableAsync
@Configuration
public class AsycTaskExecutorConfig {@Bean(name="taskExecutor1")public TaskExecutor taskExecutor1() {ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();taskExecutor.setCorePoolSize(1);taskExecutor.setMaxPoolSize(1);return taskExecutor;}@Bean(name="taskExecutor2")public TaskExecutor taskExecutor2() {ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();//最大线程数taskExecutor.setMaxPoolSize(5);//核心线程数taskExecutor.setCorePoolSize(5);//任务队列的大小taskExecutor.setQueueCapacity(5);//线程前缀名
// executor.setThreadNamePrefix();//线程存活时间taskExecutor.setKeepAliveSeconds(60);taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//线程初始化return taskExecutor;}@Bean(name="taskExecutor3")public TaskExecutor taskExecutor3() {ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();//最大线程数taskExecutor.setMaxPoolSize(5);//核心线程数taskExecutor.setCorePoolSize(5);//任务队列的大小taskExecutor.setQueueCapacity(5);//线程前缀名
// executor.setThreadNamePrefix();//线程存活时间taskExecutor.setKeepAliveSeconds(60);taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//线程初始化return taskExecutor;}@Bean(name = "asyncPoolTaskExecutor")public ThreadPoolTaskExecutor executor() {ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();//核心线程数taskExecutor.setCorePoolSize(10);//线程池维护线程的最大数量,只有在缓冲队列满了之后才会申请超过核心线程数的线程taskExecutor.setMaxPoolSize(10);//缓存队列taskExecutor.setQueueCapacity(15);//设置线程的空闲时间,当超过了核心线程出之外的线程在空闲时间到达之后会被销毁taskExecutor.setKeepAliveSeconds(60);//异步方法内部线程名称taskExecutor.setThreadNamePrefix("async-");/*** 当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略* 通常有以下四种策略:* ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。* ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。* ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)* ThreadPoolExecutor.CallerRunsPolicy:重试添加当前的任务,自动重复调用 execute() 方法,直到成功*/taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());taskExecutor.initialize();return taskExecutor;}}
相关文章:
springboot 多线程实战
先说下业务场景,业务1:基于实时轨迹数据打卡,业务2:基于非实时轨迹的时间差,计算累计时长。 简单点说就是从websocket获取到的实时数据,既要兼容不耗时操作,又要兼容耗时操作。 单线程做的话&a…...
求生之路2社区服务器sourcemod安装配置搭建教程centos
求生之路2社区服务器sourcemod安装配置搭建教程centos 大家好我是艾西,通过上文我们已经成功搭建了求生之路2的服务端。但是这个服务端是纯净的服务端,就是那种最纯粹的原版。如果想要实现插件、sm开头的命令等功能,需要安装这个sourcemod。…...
通达OAV12版本,表单及流程,定制开发总结
通达OA-V12版本,表单及流程,定制开发总结 触发器金蝶系统对接 日期:2023年8月29日 触发器 一键转交操作,不会调用触发器。 解决办法:可以按需要按步骤,关闭一键转交按钮。这里会隐藏一键转交、一键结束按钮…...
浅析Linux 物理内存外碎片化
本文出现的内核代码来自Linux4.19,如果有兴趣,读者可以配合代码阅读本文。 一、Linux物理内存外碎片化概述 什么是Linux物理内存碎片化?Linux物理内存碎片化包括两种: 1.物理内存内碎片:指分配给用户的内存空间中未…...
C#中的get和set
当我们定义属性的 get 访问器和 set 访问器时,其中的 return 和 value 分别代表以下含义: return:在 get 访问器中使用,表示返回属性的值给调用方。它用于将属性关联的字段的值返回给外部代码。value:在 set 访问器中…...
mysql8.0以上忘记密码的重置方法 - window系统
1、关闭 mysql 服务,以 管理员身份 运行命令提示符工具,执行下面的命令 net stop mysql可以在任务管理器的服务中查看状态 2、跳过 mysql 权限验证,以管理员身份运行 cmd,进入 mysql 的安装 bin 目录,执行如下指令 m…...
手写Vue3响应式数据原理
Vue3响应式数据 前言一、proxy是什么?1.1 proxy基本使用 二、实现最基本的reactive函数三、实现基本响应式系统四、完善基本响应式系统4.1 执行每一个副作用函数4.2 实现依赖收集4.2.1 基本实现 4.3 改进桶结构 五、相关面试题1.Object.defineProperty 和 Proxy 的区…...
基于PIC单片机篮球计分计时器
一、系统方案 本设计采用PIC单片机作为主控制器,矩阵键盘控制,比分,计时控制,24秒,液晶12864显示。 二、硬件设计 原理图如下: 三、单片机软件设计 1、首先是系统初始化 2、液晶显示程序 /*************…...
关于Maxwell与Kafka和数据库的监控
1.Maxwell的配置 其实就是配置两端的配置信息,都要能连接上,然后才能去传输数据 config.properties #Maxwell数据发送目的地,可选配置有stdout|file|kafka|kinesis|pubsub|sqs|rabbitmq|redis producerkafka # 目标Kafka集群地址 kafka.bootstrap.servershadoop102…...
【设计模式】Java设计模式详细讲解
一、概述 Java设计模式是Java程序设计中一种重要的最佳实践,它提供了一种框架和结构,可以帮助开发者更好地理解和设计复杂的系统。设计模式不仅仅是一种语法规则,更是一种思想和方法论,它能够帮助开发者更好地分析、设计和实现软…...
【MySQL】表的增删查改(进阶)
目录 1.数据库约束 1.1NOT NULL:非空约束 1.2UNIQUE:唯一值约束 1.3DEFAULT:默认值约束 1.4PRIMARY KEY:主键约束 1.5FOREIGN KEY:外键约束 1.6CHECK约束 2.表的设计 2.1一对一 2.2一对多 2.3多对多 3.新增…...
Vim几种跳转方式
ps: 以下时我常用的一些跳转指令,用于参考和复习记忆。还有一些后续会更新。 文件内跳转 移动光标 普通模式下左h,右l,上k,下j。(可以使用数字hlkj,实现跳跃式移动)。 字符间跳转 …...
element-ui 弹窗里面嵌套弹窗,解决第二个弹窗被遮罩层掩盖无法显示的问题
当我们在 element-ui 中使用弹窗嵌套弹窗时,会出现第二个弹窗打开时被一个遮罩层挡着,就像下面这样: 下面提供两种解决方案 : 一、第一种方案 我们查询element-ui 官网可以发现 el-dialog 有这样几个属性: 具体使用就…...
【业务功能篇76】微服务网关路由predicates断言条件-filters路由转换地址-跨域问题-多级目录树化层级设计-mybatisPlus逻辑删除
业务开发-基础业务-分类管理 启动renren-fast如果出现如下错误 -Djps.track.ap.dependenciesfalse 添加相关配置即可 分类管理 1.后端分类接口 JDK8特性:https://blog.csdn.net/qq_38526573/category_11113126.html 在后端服务中我们需要查询出所有的三级分类信…...
apache的ab工具测试网页优化效果速度以及服务器承载
今天为大家介绍一款apache自带的一种的测试网页优化效果速度以及服务器承载的工具——ab.exe。 大家在工作中或者开发中可以使用apache的ab工具来测试自己的网站并发量大小,和某个页面的访问时间。 一、基本用法 如果你是用的是apache的话,那么只要进…...
【进阶篇】MySQL 存储引擎详解
文章目录 0.前言1.基础介绍2.1. InnoDB存储引擎底层原理InnoDB记录存储结构和索引页结构InnoDB记录存储结构:InnoDB索引页结构: 3. MVCC 详解3.1. 版本号分配:3.2. 数据读取:3.3. 数据写入:3.4. 事务隔离级别ÿ…...
Spring集成【MyBatis】和【PageHelper分页插件】整合---详细介绍
一,spring集成Mybatis的概念 Spring 整合 MyBatis 是将 MyBatis 数据访问框架与 Spring 框架进行集成,以实现更便捷的开发和管理。在集成过程中,Spring 提供了许多特性和功能,如依赖注入、声明式事务管理、AOP 等 它所带来给我们的…...
PyCharm下安装配置PySide6开发环境(Qt Designer(打开,编辑)、PyUIC和PyRCC)
一.准备工作 1.安装python和pycharm并配置好环境变量 python安装路径 pycharm安装路径: python系统变量: pycharm环境变量: 注意:正常安装,并勾选ADD PATH一般会自动配好 2.在pycharm创建一个新的python的虚拟环境 …...
pytest fixture 创建一个 requests.session() 对象
当你运行这段代码时,它会执行以下操作: 1. 导入必要的库:pytest 和 requests。 2. 定义一个夹具(fixture)函数 session,使用 pytest.fixture(scopesession) 装饰器进行标记。这个夹具函数在整个测试会话期…...
深入分析负载均衡情景
本文出现的内核代码来自Linux5.4.28,为了减少篇幅,我们尽量不引用代码,如果有兴趣,读者可以配合代码阅读本文。 一、有几种负载均衡的方式? 整个Linux的负载均衡器有下面的几个类型: 实际上内核的负载均衡…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
深入解析光敏传感技术:嵌入式仿真平台如何重塑电子工程教学
一、光敏传感技术的物理本质与系统级实现挑战 光敏电阻作为经典的光电传感器件,其工作原理根植于半导体材料的光电导效应。当入射光子能量超过材料带隙宽度时,价带电子受激发跃迁至导带,形成电子-空穴对,导致材料电导率显著提升。…...
嵌入式面试常问问题
以下内容面向嵌入式/系统方向的初学者与面试备考者,全面梳理了以下几大板块,并在每个板块末尾列出常见的面试问答思路,帮助你既能夯实基础,又能应对面试挑战。 一、TCP/IP 协议 1.1 TCP/IP 五层模型概述 链路层(Link Layer) 包括网卡驱动、以太网、Wi‑Fi、PPP 等。负责…...
Python异步编程:深入理解协程的原理与实践指南
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 持续学习,不断…...
Caliper 配置文件解析:config.yaml 和 fisco-bcos.json 附加在caliper中执行不同的合约方法
Caliper 配置文件解析:config.yaml 和 fisco-bcos.json Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO…...
【Go语言基础【6】】字符串格式化说明
文章目录 零、格式化常用场景一、Go 字符串格式化核心概念二、常用格式化占位符1. 整数类型2. 浮点数类型3. 字符串与布尔类型4. 指针与通用类型 三、宽度与精度控制1. 宽度控制2. 精度控制(浮点数/字符串) 零、格式化常用场景 数值转字符串:…...
