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: рекомендуется использовать этот объект, если пул потоков управляется только в том же процессе. Он фактически управляет пулом потоков, используя собственный ScheduledExecutorService Java.
1.2 Trigger
Триггер — это ключевой класс для настройки временной задачи, время следующего выполнения метода конфигурации.
public interface Trigger {
Date nextExecutionTime(TriggerContext triggerContext);
}
Параметр TriggerContext в методе инкапсулирует время последнего выполнения задачи и время последнего выполнения.
public interface TriggerContext {
Date lastScheduledExecutionTime();
Date lastActualExecutionTime();
Date lastCompletionTime();
}
Реализация TriggerContext по умолчанию — SimpleTriggerContext, а реализация исходного кода очень проста.
Класс для реализации триггера:
- crontrigger: Использование времени выполнения задачи определения выражения cron
Такие как:scheduler.schedule(task, new CronTrigger("0 15 9-17 * * MON-FRI"));
- PeriodicTrigger: через «фиксированный период», «начальное значение задержки», «логическое значение, чтобы указать, должен ли период
интерпретироваться как параметры с фиксированной скоростью или с фиксированной задержкой 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--"); }
Примечание. Возвращаемое значение метода синхронизации может быть только пустым и не может иметь входящие параметры.
-
fixedRate: этот метод вызывается каждые 5 секунд, независимо от того, был ли выполнен предыдущий метод или нет.
/** * 每隔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--"); }
-
Полный демо-код
/** * 定时类 * 不同异步方法:定时方法只能返回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-конфигурация
Задача: управляемая аннотациями эквивалентна @EnableScheduling, которая запускает запланированную задачу.
задача: управляемая аннотациями эквивалентна @EnableScheduling, планировщик указывает пул потоков
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);
}
}
```