SpringBoot基础篇(九):SpringTask应用

      Spring3.0后提供Spring Task实现任务调度,支持按日历调度,相比Quartz功能稍简单,但是在开发基本够用,支持注解编程方式。我们这里是在SpringBoot下应用SpringTask。

1、SpirngTask入门

【入门案例】

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
 * @ClassName YwTask
 * @描述 spring task的配置类
 * @Date
 **/
@Component
@EnableScheduling //表示开启SpringTask
public class YwTask {
    private static final Logger LOGGER = LoggerFactory.getLogger(YwTask.class);
    // @Scheduled(fixedRate = 5000) //上次执行开始时间后5秒执行
// @Scheduled(fixedDelay = 5000) //上次执行完毕后5秒执行
// @Scheduled(initialDelay=3000, fixedRate=5000) //第一次延迟3秒,以后每隔5秒执行一次
    @Scheduled(cron="0/3 * * * * *")//每隔3秒执行一次
    public void task1(){
        LOGGER.info("===============测试定时任务1开始===============");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LOGGER.info("===============测试定时任务1结束===============");
    }
}

【注意】(1)在该类上使用了@Component和@EnableScheduling;其中@EnableScheduling表示开启SpringTask,如果不在配置类上添加@EnableScheduling注解,则需要在启动类上使用此注解。

(2)@Scheduled注解表示Task按照什么方式执行。

2、Cron表达式

  Cron表达式包括6部分:秒(0~59) 分钟(0~59) 小时(0~23) 月中的天(1~31) 月(1~12) 周中的天。(填写MON,TUE,WED,THU,FRI,SAT,SUN,或数字1~7 1表示MON,依次类推)
特殊字符介绍:
(1)"/"字符表示指定数值的增量;
(2)"*"字符表示所有可能的值;
(3)"-"字符表示区间范围;
(4)"," 字符表示列举;
(5)"?"字符仅被用于月中的天和周中的天两个子表达式,表示不指定值;

3、SpringTask中的注解

3.1、@EnableScheduling注解

@EnableScheduling注解表示开启SpringTask,一般放在配置类上或者是SpringBoot的启动类上。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({SchedulingConfiguration.class})
@Documented
public @interface EnableScheduling {
}

3.2、@Scheduled注解

【@Scheduled注解源码】

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {
//cron属性表示使用cron表达式
    String cron() default "";
    String zone() default "";
//fixedDelay表示以固定速率执行,单位是毫秒;上次执行完毕后多少毫秒执行
    long fixedDelay() default -1L;
    String fixedDelayString() default "";
//fixedRate表示以固定速率执行,单位是毫秒;上次执行时间开始后多少毫秒执行。
    long fixedRate() default -1L;
    String fixedRateString() default "";
    long initialDelay() default -1L;
    String initialDelayString() default "";
}

 通过源码我们需要注意试fixedRate和fixedDelay这两个属性的区别和应用。

4、SpringTask串行执行

在Spring框架下SpringTask默认是按照串行执行的。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@EnableScheduling //表示开启SpringTask
public class YwTask {    
    @Scheduled(cron="0/3 * * * * *")//每隔3秒执行一次
    public void task1(){
        LOGGER.info("===============测试定时任务1开始===============");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LOGGER.info("===============测试定时任务1结束===============");
    }
    @Scheduled(fixedRate = 3000) //上次执行开始时间后5秒执行
    public void task2(){
        LOGGER.error("===============测试定时任务2开始===============");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LOGGER.error("===============测试定时任务2结束===============");
    }
}

通过上面的代码运行,我们发现只有当任务1执行完成之后,任务2才开始执行。 

5、SpringTask并行执行

在实际的项目应用中,通常是有多个任务,且这些任务都是不相干的。这时就需要并行执行任务。如果想实现SpringTask执行并行任务,我们需要创建异步任务类实现SchedulingConfigurer和 AsyncConfigurer这两个接口,并且实现configureTasks()方法。

/**
 * @ClassName AsyncTaskConfig
 * @描述 创建异步任务配置类
 * 需要配置线程池实现多线程调度任务
 **/
@Component
@EnableScheduling
public class AsyncTaskConfig implements SchedulingConfigurer, AsyncConfigurer {
    //线程池线程数量
    private int corePoolSize = 10;
    @Bean
    public ThreadPoolTaskScheduler taskScheduler()
    {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.initialize();//初始化线程池
        scheduler.setPoolSize(corePoolSize);//线程池容量
        return scheduler;
    }

    @Override
    public Executor getAsyncExecutor() {
        Executor executor = taskScheduler();
        return executor;
    }
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.setTaskScheduler(taskScheduler());
    }
}

我们再次运行时,就会发现第四步中的代码会按照并行的方式运行。

猜你喜欢

转载自blog.csdn.net/u013089490/article/details/85160353