使用場景:數據定時增量同步,定時發送郵件,爬蟲定時抓取java
定時任務概述web
定時任務:顧名思義就是在特定/指spring
定的時間進行工做,好比咱們的手機鬧鐘,他就是一種定時的任務。多線程
實現方式:併發
1.Timer:JDK自帶的java.util.Timer;經過調度java.util.TimerTask的方式 讓程序按照某一個頻率執行,但不能在指定時間運行,通常使用較少。app
2.ScheduledExecutorService:JDK1.5增長的,位於Java.util.concurrent包種,是基於線程池設計的定時任務類,每一個調度任務都會被分配到線程池中,併發執行,互不影響。異步
3.Spring Task:spring 3.0之後新增了task,一個輕量級的Quartz,功可以用,用法簡單。jsp
4.Quartz:功能最爲強大的調度器,可讓程序在指定時間執行,也能夠按照某一個頻率執行,他還能夠動態開關,可是配置起來比較複雜,現現在開源社區中已經不少基於Quartz 實現的分佈式定時任務項目。分佈式
Timer方式ide
基於Timer實現的定時調度,目前應用較少,不推薦使用
@GetMapping("/test") public String test() { TimerTask timerTask = new TimerTask() { @Override public void run() { System.out.println("執行任務"+ LocalDateTime.now()); } }; Timer timer = new Timer(); //參數1 須要執行的任務 參數2 延遲時間毫秒 參數3 間隔時間毫秒 timer.schedule(timerTask,5000,3000); return "test"; }
ScheduledExecutorService
基於ScheduledExecutorService實現的調度任務,它與TImer很相似,但它的效果更好,多線程並行處理定時任務時,Timer運行多個TimeTask時,只要其中有一個因任務報錯沒有捕獲拋出的異常,其餘任務便會自動終止運行,使用scheduledExecutorService能夠規避這個問題
@GetMapping("/cheduled") public String cheduled() { ScheduledExecutorService service = Executors.newScheduledThreadPool(10); //參數1具體執行的任務 2首次執行的延遲時間 3任務執行間隔 4間隔時間單位 service.scheduleAtFixedRate(()->System.out.println("執行任務"+LocalDateTime.now()),0,3, TimeUnit.SECONDS); return "cheduled"; }
Spring Task(關鍵)
導入依賴
在pom.xml中添加spring-boot-starter-web依賴便可,它包含了spring-context,定時任務相關的就屬於這個JAR下的org.springframework.scheduling包中
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
定時任務
@Scheduled 定時任務的核心
cron:cron表達式,根據表達式循環執行,與fixedRate屬性不一樣的是它將時間進行了切割
fixeRate:每隔多久執行一次,無視工做時間(@Scheduled(fixedRate = 1000))假設第一次工做時間爲2018-06-15 00:00:00,工做時長爲5秒,那麼下次任務的時間就是 2018-06-15 00:00:05)
initialDelay:第一次執行延遲時間,只是作延遲的設定,與fixedDelay關係密切,配合使用。
@Async 表明任務能夠進行一步工做,由本來的串行改成並行
package com.spring.boot.utils; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.time.LocalDateTime; @Component public class SpringTaskDemo { @Async @Scheduled(cron = "0/1 * * * * *") public void scheduled1() throws InterruptedException { Thread.sleep(3000); System.out.println("scheduled1 每1秒執行一次" + LocalDateTime.now()); } @Scheduled(fixedRate = 1000) public void scheduled2() throws InterruptedException { Thread.sleep(3000); System.out.println("scheduled2 每1秒執行一次" + LocalDateTime.now()); } @Scheduled(fixedRate = 3000) public void scheduled3() throws InterruptedException { Thread.sleep(5000); System.out.println("scheduled3 航次執行完畢後間隔3秒繼續執行" + LocalDateTime.now()); } }
cron表達式在線生成:
http://www.pdtools.net/tools/becron.jsp
啓動類中@EnableScheduling註解 表示開啓對@Scheduled註解的解析;同時new ThreadPoolTaskScheduler()也是至關的關鍵,默認狀況下的private volatile int poolSize = 1;這就致使了多個任務的狀況下容易出現競爭狀況(多個任務的狀況下,若是第一個任務沒執行完畢,後續的任務將會進入等待狀態)。
@EnableAsync 表明開啓@Async異步的解析,並行化運行
@EnableAsync @EnableScheduling @SpringBootApplication public class BootApplication{ public static void main(String[] args) { SpringApplication.run(BootApplication.class,args); } @Bean public TaskScheduler taskScheduler(){ ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); taskScheduler.setPoolSize(10); return taskScheduler; } }
測試
啓動項目 觀察日誌信息以下:
scheduled2 每1秒執行一次2018-06-14T17:33:42.245 scheduled1 每1秒執行一次2018-06-14T17:33:43.030 scheduled1 每1秒執行一次2018-06-14T17:33:44.009 scheduled3 航次執行完畢後間隔3秒繼續執行2018-06-14T17:33:44.244 scheduled1 每1秒執行一次2018-06-14T17:33:45.011 scheduled2 每1秒執行一次2018-06-14T17:33:45.249 scheduled1 每1秒執行一次2018-06-14T17:33:46.008 scheduled1 每1秒執行一次2018-06-14T17:33:47.008 scheduled1 每1秒執行一次2018-06-14T17:33:48.010 scheduled2 每1秒執行一次2018-06-14T17:33:48.254 scheduled1 每1秒執行一次2018-06-14T17:33:49.005 scheduled3 航次執行完畢後間隔3秒繼續執行2018-06-14T17:33:49.247 scheduled1 每1秒執行一次2018-06-14T17:33:50.008 scheduled1 每1秒執行一次2018-06-14T17:33:51.006 scheduled2 每1秒執行一次2018-06-14T17:33:51.258 scheduled1 每1秒執行一次2018-06-14T17:33:52.006 scheduled1 每1秒執行一次2018-06-14T17:33:53.008 scheduled1 每1秒執行一次2018-06-14T17:33:54.007 scheduled3 航次執行完畢後間隔3秒繼續執行2018-06-14T17:33:54.252 scheduled2 每1秒執行一次2018-06-14T17:33:54.262 scheduled1 每1秒執行一次2018-06-14T17:33:55.007 scheduled1 每1秒執行一次2018-06-14T17:33:56.007 scheduled1 每1秒執行一次2018-06-14T17:33:57.005 scheduled2 每1秒執行一次2018-06-14T17:33:57.266 scheduled1 每1秒執行一次2018-06-14T17:33:58.007 scheduled1 每1秒執行一次2018-06-14T17:33:59.006 scheduled3 航次執行完畢後間隔3秒繼續執行2018-06-14T17:33:59.257