SpringBoot使用Scheduling实现定时任务的示例代码

 更新时间:2023年08月13日 14:46:03   作者:palm down  
Spring Boot提供了一种方便的方式来实现定时任务,即使用Spring的@Scheduled注解,通过在方法上添加@Scheduled注解,我们可以指定方法在何时执行,本文我们就给大家介绍一下SpringBoot如何使用Scheduling实现定时任务,需要的朋友可以参考下

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;
    }
}
  • 执行结果

在这里插入图片描述

先要线程异步执行

在启动类上添加 @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

ThreadPoolTaskExecutor ThreadPoolTaskScheduler 都在 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");
    }
}
  • 执行结果

在这里插入图片描述

以上就是SpringBoot使用Scheduling实现定时任务的示例代码的详细内容,更多关于SpringBoot Scheduling定时任务的资料请关注脚本之家其它相关文章!

相关文章

  • Java中JDBC连接数据库详解

    Java中JDBC连接数据库详解

    本文主要介绍了JDBC连接数据库的相关知识,具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03
  • 基于mybatis中<include>标签的作用说明

    基于mybatis中<include>标签的作用说明

    这篇文章主要介绍了基于mybatis中<include>标签的作用说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • 深入剖析Java工厂模式让你的代码更灵活

    深入剖析Java工厂模式让你的代码更灵活

    Java工厂模式是一种创建对象的设计模式,它可以在不暴露对象创建逻辑的情况下,将对象的创建委托给子类或者其他对象。本文就来深入剖析一下Java工厂模式是如何让你的代码更灵活、可扩展、易维护的
    2023-05-05
  • Java中如何获取文件的上级目录

    Java中如何获取文件的上级目录

    这篇文章主要介绍了Java中如何获取文件的上级目录问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • Java web数据可视化实现原理解析

    Java web数据可视化实现原理解析

    这篇文章主要介绍了Java web数据可视化实现原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • Springboot实现根据条件切换注入不同实现类的示例代码

    Springboot实现根据条件切换注入不同实现类的示例代码

    这篇文章主要介绍了Springboot实现根据条件切换注入不同实现类的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • Java多线程Condition接口原理介绍

    Java多线程Condition接口原理介绍

    这篇文章主要介绍了Java多线程Condition接口原理介绍,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • SpringBoot2.0整合Shiro框架实现用户权限管理的示例

    SpringBoot2.0整合Shiro框架实现用户权限管理的示例

    这篇文章主要介绍了SpringBoot2.0整合Shiro框架实现用户权限管理的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • Spring Task定时任务的配置和使用详解

    Spring Task定时任务的配置和使用详解

    本篇文章主要介绍了Spring Task定时任务的配置和使用详解,实例分析了Spring Task定时任务的配置和使用的技巧,非常具有实用价值,需要的朋友可以参考下
    2017-04-04
  • 如何对quartz定时任务设置结束时间

    如何对quartz定时任务设置结束时间

    这篇文章主要介绍了如何对quartz定时任务设置结束时间问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12

最新评论