SpringBoot中使用单例模式+ScheduledExecutorService实现异步多线程任务(若依源码学习)

场景

若依前后端分离版手把手教你本地搭建环境并运行项目:

若依前后端分离版手把手教你本地搭建环境并运行项目_本地运行若依前后端分离-CSDN博客

设计模式-单例模式-饿汉式单例模式、懒汉式单例模式、静态内部类在Java中的使用示例:

设计模式-单例模式-饿汉式单例模式、懒汉式单例模式、静态内部类在Java中的使用示例_静态类 java 饿汉-CSDN博客

Java中创建线程的方式以及线程池创建的方式、推荐使用ThreadPoolExecutor以及示例:

Java中创建线程的方式以及线程池创建的方式、推荐使用ThreadPoolExecutor以及示例_threadpoolexecutor创建线程-CSDN博客

结合以上,学习并模仿若依登录接口中异步记录登录日志的操作。

在若依登录的SysLoginService中login登录方式有异步记录登录日志的操作。

其中核心代码为:

 AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));

代码位置

注:

博客:
霸道流氓气质-CSDN博客

实现

1、先看下若依自己本身的实现

AsyncManager异步任务管理器实现


/*** 异步任务管理器***/
public class AsyncManager {private static AsyncManager me = new AsyncManager();/*** 操作延迟10毫秒*/private final int OPERATE_DELAY_TIME = 10;/*** 异步操作任务调度线程池*/private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");/*** 单例模式*/private AsyncManager() {}public static AsyncManager me() {return me;}/*** 执行任务** @param task 任务*/public void execute(TimerTask task) {executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);}/*** 停止任务线程池*/public void shutdown() {Threads.shutdownAndAwaitTermination(executor);}
}

syncManager.me()获取一个AsyncManager对象。

执行execute方法,执行任务,传入的是一个task对象,实现了Runnable接口,是一个任务,由线程Thread去执行。

用到了单例模式,具体可参考上面。

task对象通过异步工厂类创建

public class AsyncFactory {private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");/*** 记录登录信息** @param username 用户名* @param status   状态* @param message  消息* @param args     列表* @return 任务task*/public static TimerTask recordLogininfor(final String username, final String status, final String message,final Object... args) {final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));final String ip = IpUtils.getIpAddr(ServletUtils.getRequest());return new TimerTask() {@Overridepublic void run() {String address = AddressUtils.getRealAddressByIP(ip);StringBuilder s = new StringBuilder();s.append(LogUtils.getBlock(ip));s.append(address);s.append(LogUtils.getBlock(username));s.append(LogUtils.getBlock(status));s.append(LogUtils.getBlock(message));// 打印信息到日志sys_user_logger.info(s.toString(), args);// 获取客户端操作系统String os = userAgent.getOperatingSystem().getName();// 获取客户端浏览器String browser = userAgent.getBrowser().getName();// 封装对象SysLogininfor logininfor = new SysLogininfor();logininfor.setUserName(username);logininfor.setIpaddr(ip);logininfor.setLoginLocation(address);logininfor.setBrowser(browser);logininfor.setOs(os);logininfor.setMsg(message);// 日志状态if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {logininfor.setStatus(Constants.SUCCESS);} else if (Constants.LOGIN_FAIL.equals(status)) {logininfor.setStatus(Constants.FAIL);}// 插入数据SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor);}};}/*** 操作日志记录** @param operLog 操作日志信息* @return 任务task*/public static TimerTask recordOper(final SysOperLog operLog) {return new TimerTask() {@Overridepublic void run() {// 远程查询操作地点operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);}};}
}

2、下面模仿上面的实现方式,去除掉无用的业务代码,对流程进行简化。

新建全局异步任务管理器

import com.ruoyi.common.utils.Threads;
import com.ruoyi.common.utils.spring.SpringUtils;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;/*** 全局异步任务管理器*/
public class GlobalAsyncManager {//单例private static final GlobalAsyncManager instance = new GlobalAsyncManager();//延迟执行时间private final int OPERATOR_DELAY_TIME = 10;private ScheduledExecutorService executorService = SpringUtils.getBean("scheduledExecutorService");private GlobalAsyncManager(){}public static GlobalAsyncManager getInstance(){return  instance;}//执行任务public void executorTask(TimerTask task){executorService.schedule(task,OPERATOR_DELAY_TIME, TimeUnit.MILLISECONDS);}//停止任务线程池public void shutdown(){Threads.shutdownAndAwaitTermination(executorService);}
}

这里创建ScheduledExecutorService是使用的若依封装的spring工具类

停止任务线程池也是用的若依的线程相关工具类

新建异步工厂,产生任务用

import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.BusStudent;
import com.ruoyi.system.service.IBusStudentService;
import java.util.TimerTask;/*** 异步工厂,产生任务用*/
public class AsyncTaskFactory {public static TimerTask recordLogToData(String logText){return new TimerTask() {@Overridepublic void run() {BusStudent busStudent = new BusStudent();busStudent.setAddress(logText);SpringUtils.getBean(IBusStudentService.class).insertBusStudent(busStudent);}};}
}

这里模拟插入日志到数据库中,数据库的表这里随便找了一个表。

调用示例

    @Testpublic void recordLog() throws InterruptedException {Thread.sleep(1000);GlobalAsyncManager.getInstance().executorTask(AsyncTaskFactory.recordLogToData(LocalDateTime.now()+"日志内容"));Thread.sleep(3000);System.out.println(LocalDateTime.now());}

为了验证其是异步效果,这里模拟线程休眠并记录时间

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/337548.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Zookeeper设计理念与源码剖析

Zookeeper 架构理解 整体架构 Follower server 可以直接处理读请求,但不能直接处理写请求。写请求只能转发给 leader server 进行处理。最终所有的写请求在 leader server 端串行执行。(因为分布式环境下永远无法精确地确认不同服务器不同事件发生的先后…

对root用户的理解

1.什么是root用户? Windows、MacOS、Linux均采用多用户的管理模式进行权限管理。在Linux系统中,拥有最大权限的账户名为:root(超级管理员) root用户拥有最大的系统操作权限,而普通用户在许多地方的权限是受…

6.1.2捕捉图像(2)

3.捕捉按钮 在制作软件使用说明的时候,如果能把软件中的常用按钮捕捉出来再配合文字进行讲解,能让软件使用者在更短的时间内掌握软件的使用方法,如果用“PrintScreen”键截取整个屏幕然后再用相关工具去抠按钮图像的话效率是非常…

零基础学习数学建模——(一)什么是数学建模

本篇博客将详细介绍什么是数学建模。 文章目录 个人简介什么是数学建模(一)引例:高中数学里的简单线性规划问题数学建模的定义及用途数学建模的定义数学建模的用途 正确认识数学建模 个人简介 ​ 本人在本科阶段获得过国赛省一、mathorcup数…

如何利用 NFTScan Portfolio 功能分析钱包 NFT 持仓

随着 NFT 市场的扩大和投资者的增加,追踪和管理大量 NFT 资产正变得越来越复杂,无论是新手还是资深投资者,都需要借助实时的 NFT 数据作为判断依据。因此,一个能够全面分析 NFT 钱包持仓的工具就显得尤为重要。帮助投资者掌握自身…

怎么把视频设置为电脑桌面

1、打开腾讯软件中心,搜索并下载【火萤视频桌面】,不要安装(因为卸载会出错)。 2、找到下载的火萤视频桌面exe程序,以【打开压缩包】的方式打开,把其中的WPengine文件夹解压到桌面。 3、双击打开WPengine…

MySql -数据库基本概念

一、数据库的基本概念 1.为什么要学数据库? 之前我们如果想将一些数据实现永久化存储,可以怎么做呢?没错。使用IO流的技术将数据保存到本地文件中但是接下来我有这样一个需求:将下面的user.txt文件中的王五年龄修改为35 张三 2…

导波光学理论基础

导波光学理论基础 一、电磁场基本方程 1.1 麦克斯韦方程组、物质方程、边值关系 麦克斯韦方程组 麦克斯韦方程组是一组微分方程,只能求得通解 如果需要唯一的确定各场矢量,还需补充一些边界条件 线性、静止、各向同性介质的物质方程 D ⃗ ε E ⃗ …

植物大战僵尸小游戏抖音快手直播搭建弹幕插件教程

植物大战弹幕插件功能介绍 该插件由梦歌技术部团队支持开发,本插件软件通过监测抖音弹幕信息,获取礼物数据触发脚本插件对应的功能; 功能目前基本上已经完善,后期功能会陆续上线支持更新,全新的脚本监测稳定方便实用…

AI写作神器夸克:探秘创作之旅

作为一位热衷于文学创作的青年作者,我怀揣着无限的激情与好奇,荣幸地参与了此次神秘而刺激的写作征程。在这样独特的经历中,我深深地感知到了人工智能所蕴含的强大力量。 第一站:探索未知领域 在此次行程中,我体验到…

Linux系统操作命令

Linux管理 在线查询Linux命令: https://www.runoob.com/linux/linux-install.htmlhttps://www.linuxcool.com/https://man.linuxde.net/ 1.Linux系统目录结构 Linux系统的目录结构是一个树状结构,每一个文件或目录都从根目录开始,并且根目…

【SpringCloud】之网关应用(进阶使用)

🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是君易--鑨,一个在CSDN分享笔记的博主。📚📚 🌟推荐给大家我的博客专栏《SpringCloud开发之网关应用》。🎯&a…