美文网首页
006SpringBoot调度任务Scheduled

006SpringBoot调度任务Scheduled

作者: 桃子味的白开水 | 来源:发表于2019-10-31 14:55 被阅读0次

1,在springboot程序入口加入@EnableScheduling,开启调度任务

package com.springboot.myspring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

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

2.创建定时任务类

image.png
package com.springboot.myspring.task;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class ScheduledTasks {
    private static final SimpleDateFormat dataFormat=new SimpleDateFormat("HH:mm:ss");
    @Scheduled(fixedRate=5000)
    public void reportCurrentTime(){
        log.info("当前时间:{}",dataFormat.format(new Date()));
    }
}

3.详细解释

通过在方法上加@Scheduled注解,表明该方法是一个调度任务。
@Scheduled(fixedRate = 5000) :上一次开始执行时间点之后5秒再执行
@Scheduled(fixedDelay = 5000) :上一次执行完毕时间点之后5秒再执行
@Scheduled(initialDelay=1000, fixedRate=5000) :第一次延迟1秒后执行,之后按fixedRate的规则每5秒执行一次
@Scheduled(cron=” /5 “) :通过cron表达式定义规则,什么是cro表达式,自行搜索引擎。

4.注意

SpringBoot使用@scheduled定时执行任务的时候是在一个单线程中,如果有多个任务,其中一个任务执行时间过长,则有可能会导致其他后续任务被阻塞直到该任务执行完成。也就是会造成一些任务无法定时执行的错觉
解决办法:使用多线程
方式1:将@Sheduled注释的方法内部改为异步执行

//当然了,构建一个合理的线程池也是一个关键,否则提交的任务也会在自己构建的线程池中阻塞
    ExecutorService service = Executors.newFixedThreadPool(5);

    @Scheduled(cron = "0/1 * * * * ? ")
    public void deleteFile() {
        service.execute(() -> {
            log.info("111delete success, time:" + new Date().toString());
            try {
                Thread.sleep(1000 * 5);//改成异步执行后,就算你再耗时也不会印象到后续任务的定时调度了
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }

    @Scheduled(cron = "0/1 * * * * ? ")
    public void syncFile() {
        service.execute(()->{
            log.info("222sync success, time:" + new Date().toString());
        });
    }

方式2:把Scheduled配置成多线程

@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        //当然了,这里设置的线程池是corePoolSize也是很关键了,自己根据业务需求设定
        taskRegistrar.setScheduler(Executors.newScheduledThreadPool(5));
        
        
        /**为什么这么说呢?
        假设你有4个任务需要每隔1秒执行,而其中三个都是比较耗时的操作可能需要10多秒,而你上面的语句是这样写的:
        taskRegistrar.setScheduler(Executors.newScheduledThreadPool(3));
        那么仍然可能导致最后一个任务被阻塞不能定时执行
        **/
    }
}

cron例子

/*
 * cron表达式: (秒0-59) (分钟0-59) (小时0-23) (日期1-31) (月份1-12或是JAN-DEC) (星期1-7或是SUN-SAT)
 */

@Scheduled(cron = "0 0 18 * * ?")
public void notity() {

}
例子:

CRON表达式 含义
"0 0 12 * * ?"  每天中午十二点
"0 15 10 ? * *" 每天早上10:15
"0 15 10 * * ? 2005"    2005年的每天早上10:15
"0 * 14 * * ?"  每天从下午2点开始到2:59每分钟一次
"0 0/5 14 * * ?"    每天从下午2点开始到2:55结束每5分钟一次
"0 0-5 14 * * ?"    每天14:00至14:05每分钟一次
"0 10,44 14 ? 3 WED"    三月的每周三的14:10和14:44触发 
"0 15 10 ? * MON-FRI"   每个周一、周二、周三、周四、周五的10:15

相关文章

网友评论

      本文标题:006SpringBoot调度任务Scheduled

      本文链接:https://www.haomeiwen.com/subject/miktbctx.html