Spring定时器两种实现与底层

2020-07-01  本文已影响0人  笨鸡

注解方式

/**
 * Copyright (C), 2015-2020, XXX有限公司
 * FileName: ScheduledTest
 * Author:   CT
 * Date:     2020/7/1 16:57
 * Description: 定时器
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package org.ctgu.game.db.timer;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 〈一句话功能简述〉<br>
 * 〈定时器〉
 *
 * @author CT
 * @create 2020/7/1
 * @since 1.0.0
 */
@Slf4j
@Component
public class ScheduledTest {

    public static DateTimeFormatter DateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    // 注解声明式使用 - 每五秒执行一次,不支持initialDelay
    @Scheduled(cron = "*/5 * * * * *")
    public void cron1() {
        log.info(String.format("[%s] - CronTask1触发...", DateFormat.format(LocalDateTime.now())));
    }

    // 注解声明式使用 - 禁止任务执行
    @Scheduled(cron = "-")
    public void cron2() {
        log.info(String.format("[%s] - CronTask2触发...", DateFormat.format(LocalDateTime.now())));
    }

    // 注解声明式使用 - 延迟一秒开始执行,延迟间隔为5秒
    @Scheduled(fixedDelay = 5000, initialDelay = 1000)
    public void fixedDelay1(){
        log.info(String.format("[%s] - FixedDelayTask1触发...", DateFormat.format(LocalDateTime.now())));
    }

    // 注解声明式使用 - spring-boot配置文件中process.task.fixedDelay=5000  process.task.initialDelay=1000
    @Scheduled(fixedDelayString = "${process.task.fixedDelay}", initialDelayString = "${process.task.initialDelay}")
    public void fixedDelay2(){
        log.info(String.format("[%s] - FixedDelayTask2触发...", DateFormat.format(LocalDateTime.now())));
    }

    // 注解声明式使用 - 延迟一秒开始执行,每隔5秒执行一次
    @Scheduled(fixedRate = 5000, initialDelay = 1000)
    public void fixedRate1(){
        log.info(String.format("[%s] - FixedRateTask1触发...", DateFormat.format(LocalDateTime.now())));
    }

    // 注解声明式使用 - spring-boot配置文件中process.task.fixedRate=5000  process.task.initialDelay=1000
    @Scheduled(fixedRateString = "${process.task.fixedRate}", initialDelayString = "${process.task.initialDelay}")
    public void fixedRate2(){
        log.info(String.format("[%s] - FixedRateTask2触发...", DateFormat.format(LocalDateTime.now())));
    }

}

编程方式 (如 排行榜每周一结算并发放奖励——每十五分钟刷新一次Rank)

/**
 * Copyright (C), 2015-2020, XXX有限公司
 * FileName: Main
 * Author:   CT
 * Date:     2020/7/1 16:44
 * Description: 测试
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package org.ctgu.game.db.test;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.CronTask;
import org.springframework.scheduling.config.FixedDelayTask;
import org.springframework.scheduling.config.FixedRateTask;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * 〈一句话功能简述〉<br>
 * 〈测试〉
 *
 * @author CT
 * @create 2020/7/1
 * @since 1.0.0
 */
@Slf4j
public class Main {

    public static DateTimeFormatter DateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static void main(String[] args) {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(10);
        taskScheduler.initialize();
        taskRun(taskScheduler);
//        fixedDelayRun(taskScheduler);
        fixedRateRun(taskScheduler);
    }

    public static void taskRun(ThreadPoolTaskScheduler taskScheduler) {
        String cronString = "0 0 0 ? * MON";
        CronTask cronTask = new CronTask(() -> 
            log.info(String.format("[%s] - CronTask触发Get Week Rank Result...", DateFormat.format(LocalDateTime.now()))), 
                    cronString);
        taskScheduler.schedule(cronTask.getRunnable(), cronTask.getTrigger());
    }

    public static void fixedDelayRun(ThreadPoolTaskScheduler taskScheduler) {
        FixedDelayTask fixedDelayTask = new FixedDelayTask(() -> {
            log.info(String.format("[%s] - FixedDelayTask触发...", DateFormat.format(LocalDateTime.now())));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, 5000, 1000);
        Date startTime = new Date(System.currentTimeMillis() + fixedDelayTask.getInitialDelay());
        taskScheduler.scheduleWithFixedDelay(fixedDelayTask.getRunnable(), startTime, fixedDelayTask.getInterval());
    }

    public static void fixedRateRun(ThreadPoolTaskScheduler taskScheduler) {
        LocalDateTime now = LocalDateTime.now();
        int rate = 15;
        int plusTime = rate - (now.getMinute()) % rate;
        LocalTime startTime = LocalTime.of(now.getHour(), now.getMinute() + plusTime);
        LocalDateTime startDateTime = LocalDateTime.of(now.toLocalDate(), startTime);
        long startTimeStamp = startDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        long initialDelay = startTimeStamp - System.currentTimeMillis();
        System.out.println(initialDelay);
        FixedRateTask fixedRateTask = new FixedRateTask(() ->
                log.info(String.format("[%s] - FixedRateTask触发Update RankData ...", DateFormat.format(LocalDateTime.now()))),
                1000 * 60 * rate, initialDelay);
        Date sTime = new Date(startTimeStamp);
        taskScheduler.scheduleAtFixedRate(fixedRateTask.getRunnable(), sTime, fixedRateTask.getInterval());
    }

}

fixedDelay与fixedRate区别

大致用示意字符串来表示如下(每个 T1, 或 T2 代表任务执行秒数(每次任务执行时间不定),假定 fixedRate 或 fixedDelay 的值是 5 秒,用 W 表示等待的数)

fixedRate:T1T1WWWT2.T2.T2WW.T3.T3.T3.T3.T3.T4.T4.T4.T4.T4.T4.T4T5T5WWWT6.T6........

fixedDelay:T1.T1.WWWWW.T2.T2.T2WWWWW.T3.T3.T3.T3.T3.WWWWW.T4.T4.T4.T4.T4.T4.T4.WWWWWT6.T6
上一篇 下一篇

猜你喜欢

热点阅读