原文:https://blog.csdn.net/onedaycbfly/article/details/79093829
定時任務實現方式
三種:
1) Java自帶的java.util.Timer類,這個類允許你調度一個java.util.TimerTask任務。 最早的時候就是這樣寫定時任務的。
2) 開源的第三方框架: Quartz 或者 elastic-job , 但是這個比較復雜和重量級,適用於分布式場景下的定時任務,可以根據需要多實例部署定時任務。
3) 使用Spring提供的注解: @Schedule 。 如果定時任務執行時間較短,並且比較單一,可以使用這個注解。
定時任務的創建
存在兩種調度方式: 單線程和多線程
串行方式
使用的注解: @Scheduled 和 @EnableScheduling
因為是串行執行,會有阻塞問題。解決方案:1 任務提交到一個自定義線程池 2 @Async 3 使用並行方式
@Slf4j
@EnableScheduling
@Component
public class ScheduledController {
@Autowired
ScheduledServiceImpl scheduledService;
@Scheduled(cron = "0 0/2 * * * ?")
public void pushDataScheduled(){
log.info("start push data scheduled!");
scheduledService.pushData();
log.info("end push data scheduled!");
}
並行方式
當定時任務很多的時候,為了提高任務執行效率,可以采用並行方式執行定時任務,任務之間互不影響,
只要實現SchedulingConfigurer接口就可以。
/**
定時任務並行執行
**/
@EnableScheduling
@Configuration
public class ScheduledConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.setScheduler(setTaskExecutors());
}
@Bean(destroyMethod="shutdown")
public Executor setTaskExecutors(){
return Executors.newScheduledThreadPool(3); // 3個線程來處理。
}}
cron表達式
在線生成/解析 http://cron.qqe2.com/
常用: 秒、分、時、日、月、年
0 0 10,14,16 * * ? 每天上午10點,下午2點,4點
0 0 12 * * ? 每天中午12點觸發
0 0/5 0 * * ? 每5分鍾執行一次
具體更多可以參考: https://www.cnblogs.com/linjiqin/archive/2013/07/08/3178452.html
使用延遲隊列代替定時任務
在並行執行的時候,創建線程池采用了newScheduledThreadPool這個線程池。 Executors框架中存在幾種線程池的創建,一種是 newCachedThreadPool() ,一種是 newFixedThreadPool(), 一種是 newSingleThreadExecutor()
其中newScheduledThreadPool() 線程池的采用的隊列是延遲隊列。newScheduledThreadPool() 線程池的特性是定時任務能夠定時或者周期性的執行任務。
源碼:
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
其中線程池核心線程數是自己設定的,最大線程數是最大值。阻塞隊列是自定義的延遲隊列:DelayedWorkQueue()