springboot scheduling实现定时任务

news2024/11/25 12:42:38

文章目录

    • springboot实现定时任务
        • 开启springboot定时任务
            • 原因分析:
        • 配置线程池,让定时任务指定并发执行
        • 先要线程异步执行
        • springboot异步线程池设置
        • 指定线程池执行任务

springboot实现定时任务

开启springboot定时任务

  • springboot实现定时任务很简单,只需要在启动类上加上@EnableScheduling就可以
/**
 * @author liouwb
 */
@SpringBootApplication
@EnableScheduling
public class SchedulerApplication{
    public static void main(String[] args) {
        SpringApplication.run(SchedulerApplication.class, args);
    }
}
  • 编写测试类
/**
 * @author liouwb
 */
@Slf4j
@Component
public class TestJob {
    /**
     * 定时任务-串行
     * 固定一秒执行一次
     *
     * @author liouwb
     */
    @Scheduled(cron = "0/1 * * * * ?")
    public void testTask1() {
        log.info("测试任务-1");
    }
}
  • 执行结果
    在这里插入图片描述
  • 下面测试,如果让每次任务执行5秒
    /**
     * 定时任务-串行
     * 固定一秒执行一次
     *
     * @author liouwb
     */
    @Scheduled(cron = "0/1 * * * * ?")
    public void testTask1() throws InterruptedException {
        // 让每次任务执行5秒
        Thread.sleep(5 * 1000);
        log.info("测试任务-1");
    }
  • 想要的结果是1一秒执行一次
  • 实际执行结果,是6秒执行一次,线程串行执行
  • 未达到想要的接口
    在这里插入图片描述
原因分析:
  • @EnableScheduling 注解默认使用的是ThreadPoolTaskScheduler线程池,默认线程数是1
  • 下面我们看下源码
  • 我们看先@EnableScheduling 注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SchedulingConfiguration.class)
@Documented
public @interface EnableScheduling {

}
  • 看下SchedulingConfiguration
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class SchedulingConfiguration {

	@Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
		return new ScheduledAnnotationBeanPostProcessor();
	}

}
  • 看下ScheduledAnnotationBeanPostProcessor
	public ScheduledAnnotationBeanPostProcessor() {
		this.registrar = new ScheduledTaskRegistrar();
	}
  • 看下ScheduledTaskRegistrar类,这里使用的是TaskScheduler线程池
  • 默认的是ThreadPoolTaskScheduler
    在这里插入图片描述

在这里插入图片描述

配置线程池,让定时任务指定并发执行

  • 配置线程池,实现SchedulingConfigurer接口,实现configureTasks方法
/**
 * 线程池配置
 *
 * @author liouwb
 * @time 2023-07-27
 */
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskScheduler());
    }

    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        // 设置线程池数量
        taskScheduler.setPoolSize(10);
        // 设置线程池前缀
        taskScheduler.setThreadNamePrefix("parallelScheduler-");

        return taskScheduler;
    }
}
  • 执行结果
    在这里插入图片描述
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/2b2c0bae38224c8a9adb8a33652c1d67.png

先要线程异步执行

  • 在启动类上添加@EnableAsync注解
/**
 * @author liouwb
 */
@SpringBootApplication
@EnableAsync
@EnableScheduling
public class SchedulerApplication{
    public static void main(String[] args) {
        SpringApplication.run(SchedulerApplication.class, args);
    }
}
  • 再方法上添加@Async注解便可以让方法异步执行
/**
 * @author liouwb
 */
@Slf4j
@Component
public class TestJob {
    /**
     * 定时任务-串行
     * 固定一秒执行一次
     *
     * @author liouwb
     */
    @Scheduled(cron = "0/1 * * * * ?")
    public void testTask1() throws InterruptedException {
        // 让每次任务执行5秒
        Thread.sleep(5 * 1000);
        log.info("测试任务-1");
    }

    @Async
    @Scheduled(cron = "0/1 * * * * ?")
    public void testTask2() {
        log.info("测试任务-2");
    }
}
  • 执行结果,可以看到异步线程和并未用到设置的线程池
    在这里插入图片描述

springboot异步线程池设置

  • springboot异步线程池默认使用的是ThreadPoolTaskExecutor
  • ThreadPoolTaskExecutorThreadPoolTaskScheduler都在org.springframework.scheduling.concurrent
    在这里插入图片描述
  • ``
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {
  • 断点可以看到默认的异步线程池,前缀为taskScheduler-,默认核心线程数为10
  • 默认线程池名称
    在这里插入图片描述
  • 下面我们自己配置异步线程池
/**
 * 线程池配置
 *
 * @author liouwb
 */
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskScheduler());
    }

    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(10);
        // 设置线程池前缀
        taskScheduler.setThreadNamePrefix("parallelScheduler-");

        return taskScheduler;
    }

    /**
     * 配置异步线程池
     *
     * @author liouwb
     * @rutern org.springframework.core.task.TaskExecutor
     */
    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
        // 设置最大线程数
        executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 10);
        // 设置队列容量
        executor.setQueueCapacity(Runtime.getRuntime().availableProcessors() * 10);
        // 设置线程活跃时间(秒)
        executor.setKeepAliveSeconds(10);
        // 设置默认线程名称
        executor.setThreadNamePrefix("ansyScheduled-");
        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        return executor;
    }
}
  • 执行结果,可以看到配置的线程池都生效了
    在这里插入图片描述

指定线程池执行任务

  • 可以设置多个线程池
/**
 * 线程池配置
 *
 * @author liouwb
 * @time 2023-07-27
 */
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskScheduler());
    }

    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(10);
        // 设置线程池前缀
        taskScheduler.setThreadNamePrefix("parallelScheduler-");

        return taskScheduler;
    }

    /**
     * 配置异步线程池
     *
     * @author liouwb
     * @rutern org.springframework.core.task.TaskExecutor
     */
    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
        // 设置最大线程数
        executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 10);
        // 设置队列容量
        executor.setQueueCapacity(Runtime.getRuntime().availableProcessors() * 10);
        // 设置线程活跃时间(秒)
        executor.setKeepAliveSeconds(10);
        // 设置默认线程名称
        executor.setThreadNamePrefix("ansyScheduled-");
        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        return executor;
    }

    /**
     * 配置异步线程池2
     *
     * @author liouwb
     * @rutern org.springframework.core.task.TaskExecutor
     */
    @Bean
    public TaskExecutor taskExecutor2() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
        // 设置最大线程数
        executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 10);
        // 设置队列容量
        executor.setQueueCapacity(Runtime.getRuntime().availableProcessors() * 10);
        // 设置线程活跃时间(秒)
        executor.setKeepAliveSeconds(10);
        // 设置默认线程名称
        executor.setThreadNamePrefix("异步线程池2-");
        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        return executor;
    }
}
  • 在执行的时候指定线程池的名称
/**
 * @author liouwb
 */
@Slf4j
@Component
public class TestJob {
    /**
     * 定时任务-串行
     * 固定一秒执行一次
     *
     * @author liouwb
     */
    @Scheduled(cron = "0/1 * * * * ?")
    public void testTask1() throws InterruptedException {
        // 让每次任务执行5秒
        Thread.sleep(5 * 1000);
        log.info("测试任务-1");
    }

    /**
     * 异步执行
     *
     * @author liouwb
     */
    @Async
    @Scheduled(cron = "0/1 * * * * ?")
    public void testTask2() {
        log.info("测试任务-2");
    }

    /**
     * 异步执行
     * 指定使用taskExecutor2线程池
     *
     * @author liouwb
     */
    @Async(value = "taskExecutor2")
    @Scheduled(cron = "0/1 * * * * ?")
    public void testTask3() {
        log.info("测试任务-指定线程池-3");
    }
}
  • 执行结果
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Zebec Protocol 将进军尼泊尔市场,通过 Zebec Card 推动地区金融平等

流支付正在成为一种全新的支付形态,Zebec Protocol 作为流支付的主要推崇者,正在积极的推动该支付方案向更广泛的应用场景拓展。目前,Zebec Protocol 成功的将流支付应用在薪酬支付领域,并通过收购 WageLink 将其纳入旗下&#xf…

学习才是测试猿的永动力!超详细的 pytest 钩子函数 之初始钩子和引导钩子来啦

前 言 前几篇文章介绍了 pytest 点的基本使用,学完前面几篇的内容基本上就可以满足工作中编写用例和进行自动化测试的需求。从这篇文章开始会陆续给大家介绍 pytest 中的钩子函数,插件开发等等。仔细去看过 pytest 文档的小伙伴,应该都有发现…

内容创作创新技术-147seo采集工具

对于企业和个人来说,内容创作是推广和营销的重要手段。然而,手动撰写大量原创内容不仅费时费力,也有可能陷入创作的瓶颈。面对这一挑战,147采集图文自动改写原创发布应运而生。 147采集图文自动改写原创发布是一款专业、高效的工具…

js-5:==和===的区别,分别在什么情况下使用

1、等于操作符 等于操作符用两个等号()表示,如果操作数相等,则返回true。 javascript中存在隐式转换,等于操作符在比较中会先进行类型转换,再确定操作数是否相等。 遵循以下规则: 如果任一操作数…

武汉多域名https证书能保护几个域名

https证书中可以用一张https证书保护多个域名网站的不止一个,泛域名https证书和多域名https证书都是可以用一张https证书保护多个域名站点,但是两种https证书保护的域名站点类型不同,上一篇我们了解了泛域名https证书,今天就随SSL…

【基于openharmony的多路摄像头功能:USB设备插拔检测】

前言 最近项目接触的模块比较繁多而杂,因此开始写文章记录下用以总结。 目前在做的是基于openharmony3.2的多camera功能主要涉及HDF(HAL)层与framework层。 本文章涉及多路摄像头功能的第一步:支持USB摄像头插拔检测。 内容 目前openharmony在HDF层…

399. 除法求值

题目描述&#xff1a; 主要思路&#xff1a; 本题主要利用并查集的思想&#xff0c;重点是要弄明白分子和分母的指向关系以及一系列的值的变化规则。 查询时如果两个数字不在一个集合里那么结果就为-1. class Solution { public:unordered_map<string,string> f;unorde…

港联证券|早盘三大指数涨跌不一 医药商业板块涨近3%

周二&#xff08;8月8日&#xff09;&#xff0c;三大指数涨跌纷歧&#xff0c;到上午收盘&#xff0c;上证指数涨0.01%&#xff0c;报3269.29点&#xff1b;深证成指和创业板指别离跌0.06%和0.05%&#xff1b;沪深两市合计成交额5062.22亿元&#xff0c;总体来看&#xff0c;两…

通信行业实操技巧,让你的基站无人能及!

当今社会&#xff0c;通信网络已经成为人们生活和工作中不可或缺的一部分&#xff0c;而电信基站作为这一网络的支撑和枢纽&#xff0c;扮演着至关重要的角色。 因此&#xff0c;精密空调监控在现代通信基站的运维中具有重要意义&#xff0c;为通信技术的发展和进步提供了有力支…

新一代构建工具 maven-mvnd

新一代构建工具 maven-mvnd mvnd的前世今生下载安装 mvndIDEA集成 mvnd的前世今生 maven 作为一代经典的构建工具&#xff0c;流行了很多年&#xff0c;知道现在依然是大部分Java项目的构建工具的首选&#xff1b;但随着项目复杂度提高&#xff0c;代码量及依赖库的增多使得ma…

Vue电商项目--服务器

购买服务器 就是如果想要别人访问我们的项目&#xff0c;那么我们就需要服务器。 我们之前使用node搭建服务器&#xff0c;只能在局域网中访问。 购买云服务器的方式有很多&#xff1a;像阿里云&#xff0c;腾讯云等等 腾讯云 产业智变云启未来 - 腾讯 (tencent.com) 安全…

机器学习鱼书笔记(自用更新)

零、预知识 1.Numpy 使用 介绍&#xff1a;高效的操作多维数组的函数库。 安装&#xff1a;&#xff08;前提已经安装了python&#xff09; pip install numpy导入 import numpy as np创建数组 Numpy最重要的数据结构是多维数组&#xff08;ndarray&#xff09;。通过Numpy&…

关于C++静态代码扫描工具及基于jenkins流水线搭建vs报告分析工具开发的小总结

静态代码扫描&#xff09; 主要内容&#xff1a;Tscancode 报告解析插件使用1.Tscancode linux使用命令介绍2.插件jar包3.tscancode扫描生成的文件4.解析报告插件执行方式与参数说明5.解析后生成报告样式 CPPCHECK报告解析1.cppcheck 代码扫描linux命令2.解析报告插件使用 报告…

ArduPilot开源飞控之Companion Computers简单分析

ArduPilot开源飞控之Companion Computers简单分析 1. 源由2. 伴机系统2.1 APSync2.2 DroneKit2.3 FlytOS2.4 Maverick2.5 ROS2.6 Rpanion-server 3. 总结4. 参考资料 1. 源由 从稳定性&#xff0c;社区群体&#xff0c;以及开源方式的角度看&#xff0c;Ardupilot是不错的选择…

【Vue】使用print.js插件实现打印预览功能,超简单

目录 一、实现效果 二、实现步骤 【1】安装插件 【2】在需要打印的页面导入 【3】在vue文件中需要打印的部分外层套一层div&#xff0c;给div设置id。作为打印的区域 【4】在打印按钮上添加打印事件 【5】在methods中添加点击事件 三、完整代码 一、实现效果 二、实现步…

647. 回文子串

目录 一、题目 二、代码 一、题目 二、代码 双指针&#xff01;&#xff01;&#xff01; class Solution { public:bool Palindrome(string s,int i,int j){int begini;int end j;while(begin<end){if(s[begin]!s[end]){return false;}begin;end--;}return true;}int …

IPWorks S3 Delphi Edition Crack

IPWorks S3 Delphi Edition Crack IPWorksS3使集成基于云的文件存储变得容易。易于使用的组件可用于与任何S3兼容的存储提供商集成&#xff0c;如Amazon S3、Digital Ocean Spaces、Wasabi、Backblaze B2、IBM Cloud Object storage、Oracle Cloud、Linode等。强大的客户端加密…

解决Vue+Element-UI 进行From表单校验时出现了英文提示问题

说明&#xff1a;该篇博客是博主一字一码编写的&#xff0c;实属不易&#xff0c;请尊重原创&#xff0c;谢谢大家&#xff01; 问题描述 在使用form表单时&#xff0c;往往会对表单字段进行校验&#xff0c;字段为必填项时会添加required属性&#xff0c;此时自定义rules规则…

vue中全局状态存储 pinia和vuex对比 pinia比vuex更香 Pinia数据持久化及数据加密

前言 毕竟尤大佬都推荐使用pinia&#xff0c;支持vue2和vue3&#xff01; 如果熟悉vuex&#xff0c;花个把小时把pinia看一下&#xff0c;就不想用vuex了 支持选项式api和组合式api写法pinia没有mutations&#xff0c;只有&#xff1a;state、getters、actionspinia分模块不…

20个程序员接单平台分享

这题我会&#xff01;接单软件那么多&#xff0c;找到适合自己的最重要&#xff01; V2EX https://www.v2ex.com/ 先给一个“非正常选项”&#xff0c;v2ex上有一个“酷工作”板块&#xff0c;运气好的话可以在这里找到不错的单子&#xff0c;最重要的是带你开启新世界的大门…