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

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

 我们在后端执行某些耗时逻辑操作时往往会导致长时间的线程阻塞,在这种情况之下,我们往往会引一条异步线程去处理这些异步任务,如果每次都创建新的线程来处理这些任务,不仅会增加代码冗余,还可能造成线程管理混乱,影响系统性能。在我们的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),捕获并记录异常,确保线程池不会因为未捕获的异常而崩溃。
            @Override
            protected void afterExecute(Runnable r, Throwable t)
            {
                super.afterExecute(r, t);
                Threads.printException(r, t);
            }
        };
    }
}

image.gif

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);
    }
}

image.gif

/**
 * 确保应用退出时能关闭后台线程
 * @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);
        }
    }
}

image.gif

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() {
            @Override
            public 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() {
            @Override
            public void run() {
                try {
                    // 获取 HotArticleAsycTask 实例
                    HotSearchCleanupTask hotArticleAsycTask = SpringUtils.getBean(HotSearchCleanupTask.class);
                    // 执行热点文章计算任务
                    hotArticleAsycTask.cleanupOldKeywords();
                } catch (Exception e) {
                    sys_user_logger.error("清理热搜失败", e);
                }
            }
        };
    }
}

image.gif

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

/**
 * 热点文章实时计算
 * @Author GuihaoLv
 */
@Component
public class HotArticleAsycTask {
    @Autowired
    private 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());
     }
}

image.gif


相关文章
|
2月前
|
人工智能 自然语言处理 Java
大模型应用开发5-SpringAIalibaba实战
本文介绍了SpringAIAlibaba开源项目,该项目基于SpringAI构建,为阿里云通义系列模型提供Java开发实践。主要内容包括: 基础使用:配置模型API、依赖引入、调用示例,支持同步和流式调用; 多种集成方式:对接本地Ollama模型、ChatClient高级API、SSE流式输出; 核心功能实现:提示词模板、结构化输出、持久化内存、文本生成图片/语音; 高级能力:向量数据库、RAG增强检索、工具调用(Tool Calling); MCP协议:标准化工具调用方案,实现服务端工具共享;
|
2月前
|
前端开发 Java 数据库
【数据载体POJO】POJO / DO / PO / DTO / VO / BO / Query / Entity / TO 全方位对比分析
本文系统解析Java企业级开发中各类数据载体(POJO/PO/DO/Entity/BO/DTO/TO/VO/Query)的本质、分层定位与使用边界,强调分层解耦、数据安全与职责单一原则,覆盖DDD、微服务及Spring生态实践,助力构建高内聚、低耦合的健壮架构。
|
2月前
|
Linux API 云计算
零基础保姆级|阿里云计算巢+MacOS/Linux/Windows11部署OpenClaw 技能集成+大模型配置全流程
2026年,AI自动化框架OpenClaw(原Clawdbot)凭借云端+本地双部署、多模型兼容与Skills插件化扩展能力,成为个人与团队实现复杂任务自动化的核心工具。阿里云计算巢提供OpenClaw官方一键部署方案,无需手动配置环境,5分钟即可完成云端部署;本地则支持MacOS、Linux、Windows11全系统部署,搭配阿里云千问、免费Coding Plan大模型API,再通过Skills扩展能力,可实现从信息查询、文件处理到流程自动化的全场景能力。
1034 15
|
2月前
|
人工智能 Linux API
OpenClaw多Agent协作系统实操:本地+阿里云部署与千问/Coding Plan API配置全指南
2026年OpenClaw(原Clawdbot)推出的多Agent协作系统,彻底打破了单一AI智能体的能力边界,让多个AI Agent像人类团队一样实现智能分工、实时信息同步与灵活角色配置,可高效完成内容创作、软件开发、数据分析等复杂复合型任务。在实际落地过程中,开发者不仅需要掌握多Agent协作系统的基础使用逻辑,更需要完成OpenClaw在本地多系统(MacOS/Linux/Windows11)与阿里云的稳定部署,同时实现与阿里云千问大模型API、免费Coding Plan API的无缝对接,才能真正发挥多Agent协作的核心价值。本文将深度解析OpenClaw多Agent协作系统的核心
975 10
|
2月前
|
人工智能 Linux API
阿里云、本地多平台部署 OpenClaw 集成Agent Skills实战:代码仓库分析技能包开发解析
在开源项目的开发与学习过程中,开发者常常会陷入这样的困境:在代码托管平台发现优质开源项目后,克隆到本地却面对错综复杂的目录结构、冗长且信息杂乱的说明文档,甚至连核心API入口都难以定位,最终被复杂的代码体系劝退。2026年,基于OpenClaw(曾用名Clawdbot,因Logo特征被开发者亲切称为“龙虾”)框架,结合Agent Skills可复用能力模块,能够打造专属的“代码仓库百晓通”技能包,让AI成为高效的代码分析助手,快速拆解、理解各类开源项目。同时,本文将完整梳理2026年OpenClaw在阿里云及本地MacOS、Linux、Windows11系统的部署流程,详解阿里云千问大模型与免
504 3
|
2月前
|
人工智能 Linux API
阿里云+本地三系统部署 OpenClaw 及精准参数调优手册:千问/Coding Plan模型对接教程
在日常使用OpenClaw(原Clawdbot)的过程中,很多用户都会遇到输出随机、答非所问、重复啰嗦、长度失控等问题,这些并非模型能力不足,而是**温度、最大生成长度、采样参数、惩罚系数**没有匹配场景。与此同时,正确完成云端与本地部署、对接稳定大模型,是让AI稳定输出的前提。
801 17
|
2月前
|
消息中间件 JavaScript 前端开发
详解事件循环与浏览器渲染机制
摘要:浏览器采用多进程架构,渲染主线程通过事件循环机制处理HTML解析、样式计算、布局等任务。异步机制避免主线程阻塞,任务按优先级在微队列、交互队列等不同队列中调度。JS执行会阻碍渲染,因其与渲染任务共享主线程。渲染流程包含解析、样式计算、布局、分层等阶段,最终由合成线程和GPU完成绘制。transform效率高因其仅影响合成阶段,不涉及主线程。reflow是布局重计算,repaint是绘制指令更新,两者均影响性能。
|
2月前
|
消息中间件 Dubbo Java
深入剖析RocketMQ2-实战案例
本文介绍了一个基于电商场景的订单和支付系统实现方案。系统采用SpringBoot+Dubbo+Zookeeper+RocketMQ技术栈,重点解决分布式系统中的数据一致性问题。在订单模块,通过预订单生成、库存扣减、优惠券使用、余额扣减等步骤完成下单流程,并利用RocketMQ实现失败补偿机制。支付模块处理第三方支付回调,通过消息队列异步更新订单状态。系统通过分布式事务保证数据一致性,采用线程池优化消息发送性能,并提供完整的测试方案验证系统功能。本文详细阐述了技术架构、数据库设计、核心业务流程以及异常处理机制
|
2月前
|
机器学习/深度学习 存储 人工智能
大模型应用开发1-认识大模型
摘要: 本文系统介绍了大模型的基础概念、本地部署及API调用方法。首先阐述了AI及神经网络的基本原理,重点解析了Transformer架构及其在大语言模型(LLM)中的应用。其次详细对比了三种模型使用方案(开放API/云部署/本地部署)的优缺点,并以Ollama为例演示了本地部署流程,包括模型管理、交互指令和GPU加速配置。最后说明了大模型API调用规范,列举了主流大模型产品及其应用场景,强调大模型在自然语言处理、内容生成等领域的优势,以及与传统编程结合开发智能应用的可能性。全文涵盖技术原理到实践操作,为大
|
2月前
|
消息中间件 存储 Kafka
详解Kafka1-基础使用
Kafka消息队列技术指南 本文系统介绍了Kafka消息队列的核心概念与应用实践。主要内容包括: 消息队列基础 两种模型:生产者-消费者模型和发布-订阅模型 应用场景:异步处理、系统解耦、流量削峰等 Kafka核心架构 重要组件:Broker、Zookeeper、Topic、Partition等 消费者组机制实现负载均衡 消息存储与分区策略 实践操作 集群搭建与环境配置 基准测试方法与性能指标 Java API编程示例(生产者/消费者) 事务编程实现原子操作 高级特性 生产者幂等性原理与配置 事务API与隔

热门文章

最新文章