您的位置:首页 > 编程语言 > Java开发

Spring Boot系列三 Spring @EnableScheduling 定时任务用法总结

2017-04-06 19:46 1006 查看

1. 原理

1.1 TaskScheduler

TaskScheduler是spring的定时任务使用的线程池的关键类

public interface TaskScheduler {
// 通过Trigger执行任务
ScheduledFuture schedule(Runnable task, Trigger trigger);
// 指定时间执行任务
ScheduledFuture schedule(Runnable task, Date startTime);
// 指定在指定时间后,循环周期执行任务
ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period);
//  循环周期执行任务
ScheduledFuture scheduleAtFixedRate(Runnable task, long period);
// 延迟N时间,在指定日期执行
ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay);
ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay);
}


TaskScheduler有两种实现方式:

- TimerManagerTaskScheduler:使用外部对象管理线程池,如 CommonJ TimerManager,适用于多个进程共享线程池

- ThreadPoolTaskScheduler: 如果仅仅在同一进程管理线程池,则推荐使用此对象。它实际使用Java自我的ScheduledExecutorService管理线程池

1.2 Trigger

Trigger是定时任务配置的关键类,配置方法的下次执行时间

public interface Trigger {
Date nextExecutionTime(TriggerContext triggerContext);
}


方法里的参数TriggerContext是封装了任务最后执行的时间和最后执行完毕的时间

public interface TriggerContext {
Date lastScheduledExecutionTime();
Date lastActualExecutionTime();
Date lastCompletionTime();
}


TriggerContext默认的实现是SimpleTriggerContext,看源码实现非常简单

Trigger的实现类:

- CronTrigger:使用cron表达式定义任务执行时机

如:
scheduler.schedule(task, new CronTrigger("0 15 9-17 * * MON-FRI"));


- PeriodicTrigger:通过“fixed period,”,“initial delay value”,“boolean to indicate whether the period should be interpreted as a fixed-rate or a fixed-delay”3个参数配置任务执行的时机

2. 定时方法@Scheduled

通过@Scheduled定义定时任务

fixedDelay: 每次方法执行完毕后,等待Nms再执行此方法。

/**
* 每次方法执行完毕后,等待5s再执行此方法。
*  同时只能有个线程运行此方法
*/
@Scheduled(fixedDelay=5000)
public void fixedDelay() {
try {
// 执行方法需要10s
Thread.sleep(1000 * 10);
} catch (InterruptedException e) {
}
log.info("fixedDelay--");
}


注意:定时方法返回值只能是void且不能有传入参数

fixedRate: 每隔5s调用一次此方法,无论之前的方法是否执行完毕

/**
* 每隔5s调用一次此方法,无论之前的方法是否执行完毕
*  同时可能有N个线程执行此方法
*
*/
@Scheduled(fixedRate=5000)
public void fixedRate() {
try {
// 执行方法需要10s
Thread.sleep(1000 * 10);
} catch (InterruptedException e) {
}
log.info("fixedRate--");
}


initialDelay: 第一次调用此方法前的等待时间

/***
* initialDelay: 第一次调用此方法前的等待时间
*
*/
@Scheduled(initialDelay=1000, fixedRate=5000)
public void initialDelayAndfixedRate() {
log.info("initialDelayAndfixedRate--");
}


cron:通过cron配置值

/**
* 支持cron语法:
* 每个参数的意义分别是: second, minute, hour, day of month, month, day of week
*
* 如下:周一至周五,每隔5s执行一次方法
*/
@Scheduled(cron="*/5 * * * * SUN-MON")
public void cron() {
log.info("cron--");
}


完整的demo代码

/**
* 定时类
* 不同异步方法:定时方法只能返回void且不能接受任务参数
*
* @author hry
*
*/
@Component
public class ScheduleDemo {
private static final Logger log = Logger.getLogger(ScheduleDemo.class);

/**
* 每次方法执行完毕后,等待5s再执行此方法。
* 同时只能有个线程运行此方法
*/
@Scheduled(fixedDelay=5000)
public void fixedDelay() {
try {
// 执行方法需要10s
Thread.sleep(1000 * 10);
} catch (InterruptedException e) {
}
log.info("fixedDelay--");
}

/** * 每隔5s调用一次此方法,无论之前的方法是否执行完毕 * 同时可能有N个线程执行此方法 * */ @Scheduled(fixedRate=5000) public void fixedRate() { try { // 执行方法需要10s Thread.sleep(1000 * 10); } catch (InterruptedException e) { } log.info("fixedRate--"); }

/*** * initialDelay: 第一次调用此方法前的等待时间 * */ @Scheduled(initialDelay=1000, fixedRate=5000) public void initialDelayAndfixedRate() { log.info("initialDelayAndfixedRate--"); }

/**
* 支持cron语法:
* 每个参数的意义分别是: second, minute, hour, day of month, month, day of week
*
* 如下:周一至周五,每隔5s执行一次方法
*/
@Scheduled(cron="*/5 * * * * SUN-MON")
public void cron() {
log.info("cron--");
}
}


3. 定时方法启动方式

启动定时任务有以下方式

1. 注解

通过@EnableScheduling启动定时任务

```
@SpringBootApplication
@EnableScheduling // 启动定时任务
public class ScheduleApplicationWithAnnotation {
private static final Logger log = LoggerFactory.getLogger(ScheduleApplicationWithAnnotation.class);

/**
* 自定义定时任务线程池
*  如果没有,则使用默认定时任务池
* @return
*/
@Bean(destroyMethod="shutdown")
public Executor taskExecutor() {
return  new ScheduledThreadPoolExecutor(10, new ThreadFactory() {
private AtomicInteger max = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "mySchedulAnno-" + max.incrementAndGet());
}
});
}

public static void main(String[] args) {
log.info("Start ScheduleApplicationWithAnnotation.. ");
SpringApplication.run(ScheduleApplicationWithAnnotation.class, args);
}
}

```


2. XML配置

task:annotation-driven等价于@EnableScheduling,启动定时任务

task:annotation-driven等价于 @EnableScheduling, scheduler指定线程池

id指定线程池产生线程名称的前缀

<task:annotation-driven scheduler="myScheduler"/>

<task:scheduler id="myScheduler" pool-size="10"  />


```
/**
* 通过XML启动异步方法
* @author hry
*
*/
@SpringBootApplication
@ImportResource("classpath:/schedule/spring_schedule.xml")
public class ScheduleApplicationWithXML {
private static final Logger log = LoggerFactory.getLogger(ScheduleApplicationWithXML.class);

public static void main(String[] args) {
log.info("Start ScheduleApplicationWithXML.. ");
SpringApplication.run(ScheduleApplicationWithXML.class, args);
}
}
```


4. 自定义配置线程池

通过实现SchedulingConfigurer 对定时任务线程池进行更细化的配置
```
/**
* 通过实现SchedulingConfigurer对定时任务线程池进行更细致配置
* @author hry
*
*/
@Component
@Configuration
public class MySchedulingConfigurer implements SchedulingConfigurer  {

@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}

@Bean(destroyMethod="shutdown")
public Executor taskExecutor() {
return  new ScheduledThreadPoolExecutor(10, new ThreadFactory() {
private AtomicInteger max = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "myScheConfig-" + max.incrementAndGet());
}
});
}
}

```

通过@EnableScheduling启动定时方法
```
/**
* 通过@EnableScheduling启动定时方法
* 配置
*
* @author hry
*
*/
@SpringBootApplication
@EnableScheduling // 启动定时任务
public class ScheduleApplicationWithSchedulingConfigurer {
private static final Logger log = LoggerFactory.getLogger(ScheduleApplicationWithSchedulingConfigurer.class);

public static void main(String[] args) {
log.info("Start ScheduleApplicationWithSchedulingConfigurer.. ");
SpringApplication.run(ScheduleApplicationWithSchedulingConfigurer.class, args);
}
}
```


5. 代码

github
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: