基于自定义线程池手写一个异步任务管理器

server/2025/3/16 15:56:40/

我们在后端执行某些耗时逻辑操作时往往会导致长时间的线程阻塞,在这种情况之下,我们往往会引一条异步线程去处理这些异步任务,如果每次都创建新的线程来处理这些任务,不仅会增加代码冗余,还可能造成线程管理混乱,影响系统性能。在我们的Spring框架中是自带异步任务处理机制的,比如我们使用@Async 注解可以处理一些简单的异步任务,但这样确实无法精确去控制线程池资源,也无法灵活去管理任务调度,由此,我们可以去自行设计一个高效的自定义异步任务管理器去统一调度处理我们的自定义任务。

1.前置配置

自定义线程池,并将其注册到IOC容器中

 /*** 自定义线程池配置* @Author GuihaoLv**/
@Configuration
public class ThreadPoolConfig
{// 核心线程池大小private int corePoolSize = 50;// 最大可创建的线程数private int maxPoolSize = 200;// 队列最大长度private int queueCapacity = 1000;// 线程池维护线程所允许的空闲时间private int keepAliveSeconds = 300;/*** 通用任务线程池* @return*/@Bean(name = "threadPoolTaskExecutor")public ThreadPoolTaskExecutor threadPoolTaskExecutor(){ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setMaxPoolSize(maxPoolSize);executor.setCorePoolSize(corePoolSize);executor.setQueueCapacity(queueCapacity);executor.setKeepAliveSeconds(keepAliveSeconds);// 线程池对拒绝任务(无线程可用)的处理策略//当线程池满了,新任务无法加入时,CallerRunsPolicy 让提交任务的线程(即调用方线程)直接执行该任务,// 而不是丢弃或抛出异常,从而保证任务不会丢失。executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());return executor;}/*** 执行周期性或定时任务*/@Bean(name = "scheduledExecutorService")protected ScheduledExecutorService scheduledExecutorService(){//这里没有最大线程数的概念,所有线程都属于核心线程。return new ScheduledThreadPoolExecutor(corePoolSize,new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d") //设置线程名称,方便排查日志。.daemon(true).build(), //daemon(true) 使线程池中的线程成为 守护线程,即 JVM 退出时不会阻止进程终止。new ThreadPoolExecutor.CallerRunsPolicy()) //使用 CallerRunsPolicy,避免任务丢失。{//任务执行完毕后,调用 Threads.printException(r, t),捕获并记录异常,确保线程池不会因为未捕获的异常而崩溃。@Overrideprotected void afterExecute(Runnable r, Throwable t){super.afterExecute(r, t);Threads.printException(r, t);}};}
}

2.异步任务管理器配置

 /*** 异步任务管理器* AsyncManager 是 整个异步任务调度的核心,它提供了 任务执行、调度和管理。* @Author GuihaoLv*/
public class AsyncManager
{/*** 操作延迟10毫秒*/private final int OPERATE_DELAY_TIME = 10;/*** 异步操作任务调度线程池* executor 采用 ScheduledExecutorService 线程池,可以 定时执行异步任务,提高并发能力*/private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");/*** 单例模式* 采用 单例模式,确保全局只有一个 AsyncManager 实例,保证任务调度统一管理。创建单例对象*/private AsyncManager(){}//创建异步任务管理器的静态对象private static AsyncManager me = new AsyncManager();public static AsyncManager me(){return me;}/*** 使用调度线程池执行任务* @param task 任务*///TimerTask是Java编程语言中的一个抽象类,通常用于安排将来某个时间执行的任务,或者以固定的速率重复执行的任务。// 它是与Timer类一起使用的,Timer负责管理和调度这些任务。public void execute(TimerTask task){executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);}/*** 停止任务线程池*/public void shutdown(){//优雅关闭线程池Threads.shutdownAndAwaitTermination(executor);}
}
 /*** 确保应用退出时能关闭后台线程* @Author GuihaoLv*/
@Component
public class ShutdownManager
{private static final Logger logger = LoggerFactory.getLogger("sys-user");@PreDestroy //它用于在 Spring Bean 被销毁前执行清理逻辑。public void destroy(){shutdownAsyncManager();HttpUtils.shutdown();}/*** 停止异步执行任务*/private void shutdownAsyncManager(){try{logger.info("====关闭后台任务任务线程池====");AsyncManager.me().shutdown();}catch (Exception e){logger.error(e.getMessage(), e);}}}

3.异步工厂配置,将异步任务的启动逻辑都扔到异步工厂中处理

/*** 异步工厂(产生任务用)* AsyncFactory 主要用于创建异步任务,它相当于一个 "任务工厂",* 可以根据不同的需求创建不同的任务(如记录用户登录信息、记录操作日志)。** @Author GuihaoLv*/
public class AsyncFactory
{private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");// 定义任务:计算热点文章public static TimerTask calculateHotArticlesTask() {return new TimerTask() {@Overridepublic void run() {try {// 获取 HotArticleAsycTask 实例HotArticleAsycTask hotArticleAsycTask = SpringUtils.getBean(HotArticleAsycTask.class);// 执行热点文章计算任务hotArticleAsycTask.calculateHotArticles();} catch (Exception e) {sys_user_logger.error("计算热点文章失败", e);}}};}// 定义任务:定时热搜清理public static TimerTask cleanupOldKeywords() {return new TimerTask() {@Overridepublic void run() {try {// 获取 HotArticleAsycTask 实例HotSearchCleanupTask hotArticleAsycTask = SpringUtils.getBean(HotSearchCleanupTask.class);// 执行热点文章计算任务hotArticleAsycTask.cleanupOldKeywords();} catch (Exception e) {sys_user_logger.error("清理热搜失败", e);}}};}
}

4.调用异步工厂中的逻辑

/*** 热点文章实时计算* @Author GuihaoLv*/
@Component
public class HotArticleAsycTask {@Autowiredprivate StringRedisTemplate redisTemplate;private static final String LIKES_KEY = "blog:likes";private static final String FAVORITES_KEY = "blog:favorites";private static final String HOT_ARTICLES_KEY = "blog:hot"; // 存热点文章public void calculateHotArticles() {Set<String> blogIds = redisTemplate.opsForZSet().range(LIKES_KEY, 0, -1);if (blogIds == null || blogIds.isEmpty()) return;for (String blogId : blogIds) {Double likes = redisTemplate.opsForZSet().score(LIKES_KEY, blogId);Double favorites = redisTemplate.opsForZSet().score(FAVORITES_KEY, blogId);// 计算热度double hotScore = (likes != null ? likes * 5.0 : 0) +(favorites != null ? favorites * 8.0 : 0);// 热度超过阈值 500,加入热点文章if (hotScore >= 500) {redisTemplate.opsForZSet().add(HOT_ARTICLES_KEY, blogId, hotScore);System.out.println("🔥 文章 " + blogId + " 进入热点榜,热度:" + hotScore);}}}/*** 每 5 分钟执行一次的定时任务*/@Scheduled(fixedRate = 100000) // 每 5 分钟执行一次public void scheduleHotArticlesCalculation() {// 将任务交给异步任务管理器执行AsyncManager.me().execute(AsyncFactory.calculateHotArticlesTask());}
}

http://www.ppmy.cn/server/175466.html

相关文章

[设计模式]1_设计模式概览

摘要&#xff1a;设计模式原则、设计模式的划分与简要概括&#xff0c;怎么使用重构获得设计模式并改善代码的坏味道。 本篇作概览与检索用&#xff0c;后续结合源码进行具体模式深入学习。 目录 1、设计模式原理 核心原则&#xff08;语言无关&#xff09; 本质原理图 原…

深入理解 RTP、RTCP、RTMP、RTSP、HLS 及 live555 推拉流实现

流媒体技术在音视频传输中起着关键作用&#xff0c;其中 RTP、RTCP、RTMP、RTSP 和 HLS 是最常见的协议。本文将详细介绍它们的区别&#xff0c;并探讨为什么 HLS 逐渐取代 RTMP。此外&#xff0c;还将解析 RTSP 作为控制协议的作用&#xff0c;并讲解 live555 如何实现音视频的…

网络安全就业形势

网络安全是一个日益增长的行业&#xff0c;对于打算进入或转行进入该领域的人来说&#xff0c;制定一个清晰且系统的职业规划非常重要。2025年&#xff0c;网络安全领域将继续发展并面临新的挑战&#xff0c;包括不断变化的技术、法规要求以及日益复杂的威胁环境。 第一部分&am…

DeepSeek 与 ChatGPT的主要区别

DeepSeek 是由中国公司 DeepSeek AI &#xff08;杭州深度求索人工智能基础技术研究有限公司&#xff09;开发的 AI 聊天机器人&#xff0c;于 2024 年推出。相比之下&#xff0c;ChatGPT 是由美国 AI 研究实验室 OpenAI 创建的&#xff0c;自 2022 年以来就已上市。两者都是专…

【部署】ubuntu部署olmOCR

目录 一、安装依赖二、安装conda新环境和sglang三、PDF解析1. 运行2. 原始 PDF 并排查看结果3. 更换模型 四、可能出现的问题1.note: This error originates from a subprocess, and is likely not a problem with pip.2.转换单个PDF命令运行时3.ImportError: libnccl.so.2: ca…

【NLP】10. 机器学习模型性能评估指标(含多类别情况), ROC,PRC

机器学习模型性能评估指标&#xff08;含多类别情况&#xff09; 1. 模型评估指标简介 在机器学习中&#xff0c;模型的性能评估非常重要。常用的模型评估指标有&#xff1a; 准确率&#xff08;Accuracy&#xff09;精度&#xff08;Precision&#xff09;召回率&#xff0…

Dijkstra算法

Dijkstra算法&#xff08;迪杰斯特拉算法&#xff09;是一种经典的单源最短路径算法&#xff0c;用于在加权图中找到从一个源点到所有其他顶点的最短路径。它要求图中不能有负权边&#xff0c;因为负权边可能会导致算法的贪心策略失效。 Dijkstra算法的基本思想 Dijkstra算法…

matlab 火电厂给水控制系统仿真

1、内容简介 略 matlab157-火电厂给水控制系统仿真 可以交流、咨询、答疑 2、内容说明 略 摘 要 虽然现在新能源发电领域比较火爆&#xff0c;但至今火力发电厂依然在我的的发电领域中拥有很重要的地位。我国虽然还是发展中国家&#xff0c;但是近年来GDP的增长已经处于世界…