一、定時任務簡述:指定觸發規則後,按照必定的頻率自動往復執行。默認只有一個單例化的線程池(始終只有一個線程)java
去處理定時任務;只有一個線程時,多個任務須要並行(同時)執行時會產生時間差【每一個任務從執行開始spring
到結束須要的時間不一樣,單線程狀況下,只能等前一個任務結束才能開始執行下一個任務】,致使實際異步
上每一個任務不是按照指定的指定的頻率執行。能夠經過配置線程池來解決。spa
1.一、非異步定時任務:從任務開始到結束都是同一個線程(即便執行過程當中有線程阻塞)線程
【當前任務執行完畢後,纔會根據任務執行條件再次觸發】code
異步定時任務(方法上有@Asycn註解): 從任務開始,假設進入阻塞狀態,任務結束時和任務開始時不必定是component
同一個線程處理的【當前任務沒有執行完畢,但任務執行條件觸發則直接建立新線程執行任務】orm
二、相關依賴 xml
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.3.12.RELEASE </version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.3</version> </dependency>
三、 簡要的配置說明blog
3.1添加命名空間
xmlns:task="http://www.springframework.org/schema/task http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd
3.2 spring配置文件【該文件須要spring讀取】
<!-- 定時任務,配置須要掃描的包 -->
<context:component-scan base-package="com.demo.quartz" />
<!-- 用於激活那些已經在spring容器裏註冊過的bean(不管是經過xml的方式仍是經過package scanning的方式)上面的註解 可不配置 --> <context:annotation-config/>
<!-- 配置處理定時任務的線程池 --> <task:scheduler id="scheduler" pool-size="10" />
<!-- 配置處理 異步定時任務的 線程池 -->
<!--
pool-size:線程池大小 keep-alive:線程最大空閒時間
queue-capacity:隊列大小(無線程可用時,其他任務放置隊列中,隊列放滿後其餘任務只能等待)
rejection-policy:隊列任務數達到最大時,處理其餘任務的策略
--> <task:executor id="taskExecutor" pool-size="10" keep-alive="2000" rejection-policy="DISCARD_OLDEST"
queue-capacity="10" />
<!-- 配置spring定時開關--> <task:annotation-driven executor="taskExecutor" scheduler="scheduler" />
3.三、@Scheduled註解中屬性設置
cron:執行任務觸發頻率規則:cron表達式詳情查看另外一博主介紹:http://biaoming.iteye.com/blog/39532
@Scheduled(fixedRate=3000) //上一次任務 開始執行後3秒 再次執行 @Scheduled(fixedDelay=3000) //上一次 任務執行結束後 3秒,再次執行 @Scheduled(initialDelay=1000,fixedDelay=3000) //第一次延時1秒執行,之後每次任務執行完後3秒再次執行
四、簡單demo
package com.demo.quartz; import java.text.SimpleDateFormat; import java.util.Date; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component @EnableScheduling //開啓spring定時任務 @Lazy(false) //默認是true爲懶下載,此處設置false public class TestQuartz { @Scheduled(cron="0/1 * * * * ?") public void test1() { //AsyncConfigurer // ThreadPoolTaskScheduler tpt = new ThreadPoolTaskScheduler(); // System.err.println(tpt.getPoolSize()); //org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean //SchedulingConfigurer try { // 源碼相關的類 //ScheduledExecutorService //ScheduledTaskRegistrar //TaskScheduler //ThreadPoolTaskScheduler //ThreadPoolTaskExecutor //org.springframework.scheduling.config.ScheduledTaskRegistrar; Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd hh:mm:ss"); System.out.println(Thread.currentThread().getName()+"----------1-----------"+sdf.format(new Date())); } @Scheduled(cron="0/1 * * * * ?") public void test2() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd hh:mm:ss"); System.out.println(Thread.currentThread().getName()+"----------3-----------"+sdf.format(new Date())); } @Scheduled(cron="0/1 * * * * ?") public void test3() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd hh:mm:ss"); System.out.println(Thread.currentThread().getName()+"----------4-----------"+sdf.format(new Date())); } @Async @Scheduled(cron="0/1 * * * * ?") public void test4() { SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd hh:mm:ss"); try { System.err.println(Thread.currentThread().getName()+"----------2-----------查看線程名稱-阻塞前"+sdf.format(new Date())); Thread.sleep(3000); System.err.println(Thread.currentThread().getName()+"----------2-----------查看線程名稱-阻塞後"+sdf.format(new Date())); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"----------2-----------"+sdf.format(new Date())); } @Async @Scheduled(cron="0/1 * * * * ?") public void test5() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd hh:mm:ss"); System.out.println(Thread.currentThread().getName()+"----------5-----------"+sdf.format(new Date())); } @Async @Scheduled(cron="0/1 * * * * ?") public void test6() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd hh:mm:ss"); System.out.println(Thread.currentThread().getName()+"----------6-----------"+sdf.format(new Date())); } }
五、效果圖
--------------該數字(表示的任務編號)-----------------------
六、定時任務執行流程源碼解析