Spring Task单机定时任务(使用及阻塞问题解决)

一、介绍

SpringTask是Spring自主研发的定时任务工具,并且存在于Spring体系中,不需要添加任何依赖
Spring Boot 默认在无任何第三方依赖的情况下使用 spring-context 模块下提供的定时任务工具 Spring Task。

  • 我们只需要使用 @EnableScheduling 注解就可以开启相关的定时任务功能
@SpringBootApplication
@EnableTransactionManagement //开启注解方式的事务管理
@Slf4j
@EnableCaching
@EnableScheduling
public class SkyApplication {
    public static void main(String[] args) {
        SpringApplication.run(SkyApplication.class, args);
        log.info("server started");
    }
}

二、SpringTask使用

@Scheduled的常见用法,包括:固定速率执行、固定延迟执行、初始延迟执行、使用 Cron 表达式执行定时任务。

Cron 表达式: 主要用于定时作业(定时任务)系统定义执行时间或执行频率的表达式,你可以通过 Cron 表达式进行设置定时任务每天或者每个月什么时候执行等等操作。
推荐一个在线Cron表达式生成器:https://cron.qqe2.com/

@Component
public class ScheduledTasks {
    private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    /**
     * fixedRate:固定速率执行。每5秒执行一次。
     */
    @Scheduled(fixedRate = 5000)
    public void reportCurrentTimeWithFixedRate() {
        log.info("Current Thread : {}", Thread.currentThread().getName());
        log.info("Fixed Rate Task : The time is now {}", dateFormat.format(new Date()));
    }

    /**
     * fixedDelay:固定延迟执行。距离上一次调用成功后2秒才执。
     */
    @Scheduled(fixedDelay = 2000)
    public void reportCurrentTimeWithFixedDelay() {
        try {
            TimeUnit.SECONDS.sleep(3);
            log.info("Fixed Delay Task : The time is now {}", dateFormat.format(new Date()));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * initialDelay:初始延迟。任务的第一次执行将延迟5秒,然后将以5秒的固定间隔执行。
     */
    @Scheduled(initialDelay = 5000, fixedRate = 5000)
    public void reportCurrentTimeWithInitialDelay() {
        log.info("Fixed Rate Task with Initial Delay : The time is now {}", dateFormat.format(new Date()));
    }

    /**
     * cron:使用Cron表达式。 每分钟的1,2秒运行
     */
    @Scheduled(cron = "1-2 * * * * ? ")
    public void reportCurrentTimeWithCronExpression() {
        log.info("Cron Expression: The time is now {}", dateFormat.format(new Date()));
    }
}

Cron

cron表达式是一个字符串,字符串以5或6个空格隔开,分开共6或7个域,每一个域代表一个含义。

cron 表达式语法:
格式:[秒] [分] [小时] [日] [月] [周] [年]

三、实例

外卖项目中,使用springtask对订单设计定时任务:
处理超时订单(超过15min 修改status)
处理“派送中”订单(每日凌晨1点,status设为完成)

/**
 * 自定义定时任务,实现订单状态定时处理
 */
@Component
@Slf4j
public class OrderTask {

    @Autowired
    private OrderMapper orderMapper;

    /**
     * 处理支付超时订单
     */
    @Scheduled(cron = "0 * * * * ?")
    public void processTimeoutOrder(){
        log.info("处理支付超时订单:{}", new Date());
        ...
    }

    /**
     * 处理“派送中”状态的订单
     */
    @Scheduled(cron = "0 0 1 * * ?")
    public void processDeliveryOrder(){
        log.info("处理派送中订单:{}", new Date());
        ...
    }

}

四、SpringTask阻塞问题

Spring 的定时任务默认是单线程执行
也就是说,如果任务执行时间超过定时任务间隔时间,不管是同一个定时任务还是不同的定时任务,下一个任务都会被阻塞。
举个例子:

@Component
@Slf4j
public class TaskTest {
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
    private List<Integer> index = Arrays.asList(6, 6, 2, 3);

    int i = 0;
    @Scheduled(fixedRate = 5000)//固定速率,每隔5秒一次
    public void reportCurrentTimeWithFixedRate() {
    	log.info("Current Thread : {}", Thread.currentThread().getName());
        if (i == 0) {
            log.info("Start time is {}", dateFormat.format(new Date()));
        }
        if (i < 5) {
            try {
                TimeUnit.SECONDS.sleep(index.get(i));
                log.info("Fixed Rate Task : The time is now {}", dateFormat.format(new Date()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            i++;
        }
    }
}

在这里插入图片描述
在这里插入图片描述

解决方法

自定义线程池执行 scheduled task:
默认情况下,@Scheduled任务都在Spring创建的大小为1的默认线程池中执行。上面可以看出来:scheduling-1

1、实现SchedulingConfigurer接口

实现SchedulingConfigurer接口的 configureTasks 的类即可,这个类需要加上 @Configuration 注解。


@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
    private final int POOL_SIZE = 10;

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();

        threadPoolTaskScheduler.setPoolSize(POOL_SIZE);
        threadPoolTaskScheduler.setThreadNamePrefix("my-scheduled-task-pool-");
        threadPoolTaskScheduler.initialize();

        scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
    }
}

实现SchedulingConfigurer接口后,定时任务会变成多线程执行。不同的定时任务之间互不影响,同一个定时任务(方法)依然会有被阻塞的机制。
如果定时任务交给线程池处理,则下一个任务不会被阻塞。
在这里插入图片描述

二、加入线程池

我们采用的是加入注解@Async@EnableAsync

从Spring3开始提供了@Async注解,该注解可以被标注在方法上,以便异步地调用该方法。调用者将在调用时立即返回,方法的实际执行将提交给Spring TaskExecutor的任务中,由指定的线程池中的线程执行。

@Component
@EnableAsync
@Slf4j
public class TaskTest {
        private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

        /**
         * fixedDelay:固定延迟执行。距离上一次调用成功后2秒才执。
         */
        //@Async
        @Scheduled(fixedDelay = 2000)
        public void reportCurrentTimeWithFixedDelay() {
            log.info("Current Thread : {}", Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(3);
                log.info("Fixed Delay Task : The time is now {}", dateFormat.format(new Date()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

固定延迟2秒 sleep3秒,也就是 5秒一次。
未使用@Async
在这里插入图片描述

1、在使用的类上加@EnableAsync注解 开启异步
2、方法上添加@Async注解
之后 是 每2秒执行一次。
在这里插入图片描述
学习:https://github.com/Snailclimb/springboot-guide

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity - Cinemachine

动态获取Cinemachine的内部组件 vCam.GetCinemachineComponent<T>() 动态修改Cinemachine的Transposer属性 var vCamComp transfrom.GetComponent<CinemachineVirtualCamera>(); var transposerComp vCamComp.GetCinemachineComponent<CinemachineTransposer&…

【Linux】gcc/g++ gdb 使用

目录 1&#xff0c;背景知识 2&#xff0c;gcc 如何完成 1&#xff0c;预处理(进行宏替换) 2&#xff0c;编译&#xff08;生成汇编&#xff09; 3&#xff0c;汇编&#xff08;生成机器可识别代码&#xff09; 4&#xff0c;连接&#xff08;生成可执行文件或库文件&…

SpringCloud微服务:Nacos快速入门

目录 第一步&#xff1a;cloud-demo的pom文件 第二步&#xff1a;user-service的pom文件 第三步&#xff1a; user-service的yml文件 第四步&#xff1a;order-service的pom文件 第五步&#xff1a; order-service的yml文件 运行 访问数据 1.Nacos服务搭建 下载安装包 …

IDEA创建SpringBoot的多模块项目教程

最近在写一个多模块的SpringBoot项目&#xff0c;基于过程总了一些总结&#xff0c;故把SpringBoot多个模块的项目创建记录下来。 首先&#xff0c;先建立一个父工程&#xff1a; &#xff08;1&#xff09;在IDEA工具栏选择File->New->Project &#xff08;2&#xff0…

【AI视野·今日NLP 自然语言处理论文速览 第六十二期】Wed, 25 Oct 2023

AI视野今日CS.NLP 自然语言处理论文速览 Wed, 25 Oct 2023 (showing first 100 of 112 entries) Totally 100 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers MuSR: Testing the Limits of Chain-of-thought with Multistep Soft R…

电脑监控软件:保护企业核心信息资产,防止数据泄露

电脑监控软件&#xff1a;保护企业核心信息资产&#xff0c;防止数据泄露 随着信息技术的飞速发展&#xff0c;电脑已经成为了企业中必不可少的办公工具。然而&#xff0c;与此同时&#xff0c;企业的核心信息资产也面临着越来越大的安全风险。 下载使用安企神电脑屏幕监控软…

LVGL案例分享--手把手教你移植到T113-i国产工业开发板

市面上有许多嵌入式GUI库可供选择&#xff0c;包括开源GUI库和闭源GUI库&#xff0c;开源GUI库&#xff1a;LVGL&#xff0c;EmWin等&#xff1b;闭源GUI库&#xff1a;TouchGFX&#xff0c;柿饼GUI等。 本篇文章主要描述如何将LVGL8.1移植到创龙科技的T113-i的开发板上。 LV…

vue3+vant 实现树状多选组件

vue3vant 实现树状多选组件 需求描述效果图代码父组件引用selectTree组件 tree组件数据格式 需求描述 移动端需要复刻Pc端如上图的功能组件&#xff0c;但vant无组件可用&#xff0c;所以自己封装一个。 效果图 代码 父组件引用 import TreeSelect from "/selectTree.vu…

小型内衣洗衣机什么牌子好?性价比高的迷你洗衣机推荐

现在洗内衣内裤也是一件较麻烦的事情了&#xff0c;在清洗过程中还要用热水杀菌&#xff0c;还要确保洗衣液是否有冲洗干净&#xff0c;还要防止细菌的滋生等等&#xff0c;所以入手一款小型的烘洗全套的内衣洗衣机是非常有必要的&#xff0c;专门的内衣洗衣机可以最大程度减少…

移交计划书、移交确认单

项目移交过程文件&#xff1a; 1、移交计划书 2、移交确认单 1、移交计划 2、移交确认单

2023年03月 Scratch(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

一、单选题(共25题,每题2分,共50分) 第1题 下列说法不正确的是?( ) A:可以从声音库中随机导入声音 B:可以录制自己的声音上传 C:可以修改声音的大小 D:不能修改声音的速度 答案:D 针对声音可以进行导入,上传,修改声音大小和速度这些操作,故正确答案选择D。…

牛只识别 牛脸识别 个体识别 身份识别

融合YOLOv5s与通道剪枝算法的奶牛轻量化个体识别方法 Light-weight recognition network for dairy cows based on the fusion of YOLOv5s and channel pruning algorithm 论文链接 知网链接 点击进入正文 该文章讨论了奶牛花斑、光照条件、不同剪枝方法、不同剪枝率对准确率的…

Power Automate-当收到HTTP请求时触发流程

选择创建自动化云端流&#xff0c;点跳过 第一个操作搜索HTTP&#xff0c;点击当收到HTTP请求时 第一个下拉框选择Anyone&#xff0c;给任何人提供访问权限&#xff0c;当然也可以根据需求选择 点击使用示例有效负载生成架构 写入JSON&#xff0c;点击完成 正文JSON架构就自动生…

Tosca 2023x 新功能介绍

Tosca/Structure的功能增强 热优化功能增强 在优化过程中&#xff0c;支持将对流边界条件转移至新创建的表面&#xff0c;方便更加真实地模拟传热行为。支持恒定传导。多物理场优化能力增强。通过使用多个输入面板对热和结构荷载进行分别输入&#xff0c;以支持同时对热和结构…

校园跑腿小程序源码系统+多校园版+取快递+食堂超市跑腿+外卖 带完整的搭建教程

大家好啊&#xff0c;又到了罗峰给大家分享源码的时间啦。今天要给大家分享的是一款校园跑腿小程序源码系统。这款系统功能十分强大&#xff0c;开发了多校园版。众所周知&#xff0c;校园跑腿的发展是从外卖配送一点点演变过来的&#xff0c;而校园跑腿的基础性服务项目就是帮…

【YOLOv7/YOLOv5系列算法改进NO.47】改进激活函数为GELU

文章目录 前言一、解决问题二、基本原理三、​添加方法四、总结 前言 作为当前先进的深度学习目标检测算法YOLOv7&#xff0c;已经集合了大量的trick&#xff0c;但是还是有提高和改进的空间&#xff0c;针对具体应用场景下的检测难点&#xff0c;可以不同的改进方法。此后的系…

modbus转profinet网关连接PLC与变频器控制摆辊应用在涂布机案例

通过兴达易控modbus转profinet网关的应用&#xff0c;PLC能够直接与变频器进行通讯&#xff0c;并实现对摆辊的精确控制。兴达易控modbus转profinet网关&#xff08;XD-MDPN100&#xff09;作为一个高性能的转换设备&#xff0c;能够稳定可靠地完成modbus和profinet之间的数据转…

智慧城市安全监控的新利器

在传统的城市管理中&#xff0c;井盖的监控一直是一个难题&#xff0c;而井盖异动传感器的出现为这一问题提供了有效的解决方案。它具有体积小、重量轻、安装方便等特点&#xff0c;可以灵活地应用于各种类型的井盖&#xff0c;实现对城市基础设施的全方位监控。 智能井盖监测终…

《低代码指南》——国内首个向量数据库标准亮相,腾讯云联合50家企业共同编制

11月15日,在腾讯云向量数据库技术及产业峰会上,腾讯云全面升级向量数据库多项核心性能,最高支持千亿级向量规模和500万QPS峰值能力,同时和信通院一起联合50多家企业共同发布了国内首个向量数据库标准,推进向量数据库及大模型相关产业走向大规模应用。 腾讯集团高级执行副总…

[修改Linux下ssh端口号]解决无法修改sshd_config无法修改

前言&#xff1a;写本文的前因是本人的阿里云服务器经常被黑客暴力破解ssh的22端口号。再网络上搜索解决都是说使用root权限进行修改&#xff0c;但本人在root下也无法成功进行修改sshd_config文件。所以在大量搜索下终于找到了解决方案&#xff0c;现在分享出来给有需要的人使…