springboot 定时任务之@Scheduled

spring3.0版本之后自带定时任务,提供了@EnableScheduling注解和@Scheduled注解来实现定时任务功能。

今天咱们先分享一下,基于注解的姿势。

基于注解的的定时任务,其实使用起来比较简单,首先在任务类上添加 @EnableScheduling注解即可。

当然,也可以加载任务执行类上。

@EnableScheduling
@SpringBootApplication
public class TestApplication {
    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
}
@Component
@EnableScheduling
public class TestTask {

    @Scheduled(cron = "0/10 * * * * ?")
    public void test1() {
        System.out.println(Thread.currentThread().getName() + "have a test1");
    }


    @Scheduled(cron = "0/13 * * * * ?")
    public void test2() {
        System.out.println(Thread.currentThread().getName() + "have a  test");
    }
}

定时任务创建

  1. 基于cron表达式的,
  @Scheduled(cron = "0/10 * * * * ?")
    public void test2() {
        System.out.println(Thread.currentThread().getName() + "cronb");
    }

如上,每10s执行一次。

2 基于fixedRate

 @Scheduled(fixedRate = 1000 * 1)
    public void test2() {
        System.out.println(Thread.currentThread().getName() + " fixedRate");
    }


这个属性是在上一个调用开始之后,再次调用的间隔时间,不需要等待上次调用结束,这样会导致存在重复执行的问题。

当然,如果在这个间隔时间内,比如1s内能执行完,也可以使用此方式。


3 基于fixedDelay

 @Scheduled(fixedDelay  = 1000 * 1)
    public void test2() {
        System.out.println(Thread.currentThread().getName() + "fixedDelay");
    }

这个属性和fixedRate是反着的,这个意思是,拿上边的例子来讲的话,会在方法体中执行完成后的延迟ss开始执行。

注:对定时任务的增加@Component注解,交给spring容器去管理。


默认情况下,如果什么不进行配置,会存在一个问题,系统中所有的定时任务是都是使用一个线程去执行的,什么意思呢,假设同一个时刻有2个定时任务需要执行,那只可能有一个定时任务在执行,所以,若果解决这个问题,有两种解决方案。一个是定义任务调度线程池,另一个是自定义线程池,使用@Async异步执行的方式。

首先第一种方式:在配置类中 @configure 配置如下

   /**
     * 执行周期性或定时任务
     */
    @Bean(name = "scheduledExecutorService")
    protected ScheduledExecutorService scheduledExecutorService()
    {
        return new ScheduledThreadPoolExecutor(corePoolSize,
                new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build())
        {
            @Override
            protected void afterExecute(Runnable r, Throwable t)
            {
                super.afterExecute(r, t);
                Threads.printException(r, t);
            }
        };
    }

    @Bean
    public TaskScheduler taskScheduler(){
        ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
        executor.setPoolSize(10);
        executor.setThreadNamePrefix("my task-");
        return  executor;
    }

输出结果

my task-1---> test
my task-2---> test2
my task-1---> test

.还有一种,是通过框架自带的多线程,来处理。。 上代码。。


@Component
@EnableScheduling
@EnableAsync
public class TestTask {

    @Async
    @Scheduled(cron = "0/10 * * * * ?")
    public void test1() {
        System.out.println(Thread.currentThread().getName() + "TEST1");
    }


    @Scheduled(cron = "0/13 * * * * ?")
    public void test2() {
        System.out.println(Thread.currentThread().getName() + "TEST2");
    }
}

执行结果如下:

my task-2TEST2
SimpleAsyncTaskExecutor-2TEST1
SimpleAsyncTaskExecutor-3TEST1
my task-3TEST2
my task-1TEST2
SimpleAsyncTaskExecutor-4TEST1
SimpleAsyncTaskExecutor-5TEST1
my task-3TEST2
SimpleAsyncTaskExecutor-6TEST1

还有一种支持可动态修改执行时间的定时任务方式

说白了,就是在不停服务的情况下,修改执行的时间。

首先,在定时任务类商@EnabledScheduling 注解不可少,关键的实现SchedulingConfigurer接口。

其次,设置cron, 即 自动执行的时间点。

第三,动态获取cron,通过此处,在外边灵活修改执行时间

最后,设置任务触发器,触发任务执行。

直接上代码

package com.lianxin.web.controller.schedul;


import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.util.Date;


@Component
@EnableScheduling
@Slf4j
public class TaskCronChange implements SchedulingConfigurer {

    public static String cron;

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        cron = "0/1 * * * * *"; // 项目启动时,会加载此配置
        log.info("11111111111");
        Runnable task = new Runnable() {
            @Override
            public void run() {
                log.info("222222222222");
            }
        };

        Trigger trigger = new Trigger(){
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                log.info("333333333333");
                cron = "0/1 * * * * *";// TODO 此处获取最新的执行时间
                CronTrigger cronTrigger = new CronTrigger(cron);
                Date date = cronTrigger.nextExecutionTime(triggerContext);
                log.info("44444444444");
                return date;
            }
        };
        scheduledTaskRegistrar.addTriggerTask(task,trigger);
    }



}

要说明的是,更新执行时间,是每次在执行任务之后,再去更新执行时间,所以,当你修改一次执行时间之后,需要在执行完一次任务之后,才会更新这个执行时间,这样,下次的任务执行的时候,才会按照最新的任务执行时间去执行。

核心是使用ScheduledTaskRegistrar.addTriggerTask方法去更新任务的执行时间。

好,先说到这,下回分享 cron的用法

展开阅读全文

页面更新:2024-02-19

标签:内能   触发器   下回   注解   表达式   说白了   线程   属性   加载   代码   方式   时间   方法   动态   最新   科技

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top