摘要:定時(shí)任務(wù)間隔時(shí)間方式執(zhí)行一次定時(shí)任務(wù)線程休眠規(guī)定時(shí)間類類允許調(diào)度一個(gè)任務(wù)。引入依賴配置測(cè)試執(zhí)行一次定時(shí)任務(wù)使用注解是為定時(shí)任務(wù)而生的一個(gè)注解,查看注解的源碼表達(dá)式接收一個(gè)。
本文旨在用通俗的語言講述枯燥的知識(shí)
定時(shí)任務(wù)作為一種系統(tǒng)調(diào)度工具,在一些需要有定時(shí)作業(yè)的系統(tǒng)中應(yīng)用廣泛,如每逢某個(gè)時(shí)間點(diǎn)統(tǒng)計(jì)數(shù)據(jù)、在將來某個(gè)時(shí)刻執(zhí)行某些動(dòng)作...定時(shí)任務(wù)在主流開發(fā)語言均提供相應(yīng)的API供開發(fā)者調(diào)用,在Java中,實(shí)現(xiàn)定時(shí)任務(wù)有很多種方式,原生的方式實(shí)現(xiàn)一個(gè)完整定時(shí)任務(wù)需要由Timer、TimerTask兩個(gè)類,Timer是定時(shí)器類,用來按計(jì)劃開啟后臺(tái)線程執(zhí)行指定任務(wù),TimerTask一個(gè)抽象類,它的子類代表一個(gè)可以被Timer計(jì)劃的任務(wù)。除此之外,還可以用ScheduledExecutorService類或者使用第三方j(luò)ar庫Quartz,其中Quartz是一個(gè)優(yōu)秀的定時(shí)任務(wù)框架,發(fā)展至今已經(jīng)非常成熟,以致后來其他的定時(shí)任務(wù)框架的核心思想或底層大多源于Quartz。
springboot作為Java的一種開發(fā)框架,在springboot項(xiàng)目中實(shí)現(xiàn)定時(shí)任務(wù)不僅可以使用Java提供的原生方式,還可以使用springboot提供的定時(shí)任務(wù)API,下面,小編把Java原生和springboot所有的實(shí)現(xiàn)定時(shí)任務(wù)的方式做一個(gè)整合。
文章提綱:1. 線程實(shí)現(xiàn)
1、使用線程
2、使用Timer類
3、使用ScheduledExecutorService類
4、使用Quartz
5、使用spring的@Scheduled注解
6、cron表達(dá)式
利用線程可以設(shè)定休眠時(shí)間的方式可以實(shí)現(xiàn)簡單的定時(shí)任務(wù)邏輯。
public static void main(String[] args){ //定時(shí)任務(wù)間隔時(shí)間 int sleepTime=2*1000; new Thread(new Runnable() { @Override public void run() { while (true){ try { System.out.println("Thread方式執(zhí)行一次定時(shí)任務(wù)"); //線程休眠規(guī)定時(shí)間 Thread.sleep(sleepTime); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); }2. Timer類
Timer類允許調(diào)度一個(gè)TimerTask任務(wù)。使用這種方式可以讓你的程序按照某一個(gè)頻度執(zhí)行。
public static void main(String[] args){ int sleepTime=2*1000; TimerTask timerTask = new TimerTask() { @Override public void run() { System.out.println("Timer方式執(zhí)行一次定時(shí)任務(wù)"); } }; new Timer().schedule(timerTask,1,sleepTime); }3. ScheduledExecutorService類
ScheduledExecutorService,是基于線程池設(shè)計(jì)的定時(shí)任務(wù)類,每個(gè)調(diào)度任務(wù)都會(huì)分配到線程池中的一個(gè)線程去執(zhí)行,也就是說,任務(wù)是并發(fā)執(zhí)行,互不影響。
因此,基于ScheduledExecutorService類的定時(shí)任務(wù)類,歸根到底也是基于線程的調(diào)度實(shí)現(xiàn)的。
public static void main(String[] args){ int sleepTime=2*1000; ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(); scheduledExecutor.scheduleAtFixedRate( new Runnable() { @Override public void run() { System.out.println("ScheduledExecutorService方式執(zhí)行一次定時(shí)任務(wù)"); } } ,1,sleepTime, TimeUnit.SECONDS); }4. 整合Quartz
Quartz是一個(gè)完全由Java編寫的開源作業(yè)調(diào)度框架,為在 Java 應(yīng)用程序中進(jìn)行作業(yè)調(diào)度提供了簡單卻強(qiáng)大的機(jī)制,要理解它的使用方式,需要先理解它的幾個(gè)核心概念:
Job: 表示一個(gè)工作,要執(zhí)行的具體內(nèi)容。此接口中只有一個(gè)方法,如下:
void execute(JobExecutionContext context)
JobDetail: 表示一個(gè)具體的可執(zhí)行的調(diào)度程序,Job 是這個(gè)可執(zhí)行程調(diào)度程序所要執(zhí)行的內(nèi)容,另外 JobDetail 還包含了這個(gè)任務(wù)調(diào)度的方案和策略。
Trigger: 代表一個(gè)調(diào)度參數(shù)的配置,什么時(shí)候去調(diào)。
Scheduler: 代表一個(gè)調(diào)度容器,一個(gè)調(diào)度容器中可以注冊(cè)多個(gè) JobDetail 和Trigger。當(dāng) Trigger 與 JobDetail 組合,就可以被 Scheduler 容器調(diào)度了。
有了這些概念之后,我們就可以把Quartz整合到我們的springboot項(xiàng)目中了。
引入quartz依賴
org.springframework.boot spring-boot-starter-quartz
配置
@Configuration public class QuartzConfig { @Bean public JobDetail quartzDetail(){ return JobBuilder.newJob(QuartzTest.class).withIdentity("QuartzTest").storeDurably().build(); } @Bean public SimpleTrigger quartzTrigger(){ SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(10) .repeatForever(); return TriggerBuilder.newTrigger().forJob(quartzDetail()) .withIdentity("QuartzTest") .withSchedule(scheduleBuilder) .build(); } }
測(cè)試
public class QuartzTest extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext jobExecutionContext){ System.out.println("quartz執(zhí)行一次定時(shí)任務(wù) "); } }5. 使用Scheduled注解
@Scheduled是spring為定時(shí)任務(wù)而生的一個(gè)注解,查看注解的源碼:
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Repeatable(Schedules.class) public @interface Scheduled { //cron表達(dá)式 String cron() default ""; //接收一個(gè)java.util.TimeZone#ID。 String zone() default ""; //上一次執(zhí)行完畢時(shí)間點(diǎn)之后多長時(shí)間再執(zhí)行 long fixedDelay() default -1; //支持占位符形式的字符串類型的fixedDelay String fixedDelayString() default ""; //上一次開始執(zhí)行時(shí)間點(diǎn)之后多長時(shí)間再執(zhí)行 long fixedRate() default -1; //支持占位符形式的字符串類型的fixedRateString String fixedRateString() default ""; //第一次延遲多長時(shí)間后再執(zhí)行 long initialDelay() default -1; //支持占位符形式的字符串類型的initialDelay String initialDelayString() default ""; }
可以看出:Scheduled注解中的參數(shù)用來設(shè)置“定時(shí)”動(dòng)作,通常情況下,比較常用的參數(shù)是cron(),這意味著我們需要學(xué)會(huì)一些cron表達(dá)式相關(guān)的語法,但由于內(nèi)容較多,篇幅較長,在這里暫不鋪開講解,我們把cron語法相關(guān)放到文章最后,在此先講解如何用Scheduled注解來實(shí)現(xiàn)定時(shí)任務(wù)。
開啟定時(shí)任務(wù)支持
@SpringBootApplication /** * 開啟定時(shí)任務(wù)支持 */ @EnableScheduling public class TestApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(TestApplication.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(this.getClass()); } }
使用
@Component public class ScheduledTest { private Logger logger = LoggerFactory.getLogger(ScheduledTest.class); /** * 每15秒執(zhí)行一次定時(shí)任務(wù) */ @Scheduled(cron = "0/15 * * * * ? ") public void testCron(){ logger.info("Scheduled 執(zhí)行一次定時(shí)任務(wù)"); } }6. cron表達(dá)式
cron表達(dá)式是一個(gè)字符串其語法為:
[秒] [分] [小時(shí)] [日] [月] [周] [年]
其中[年]為非必填項(xiàng),因此通常cron表達(dá)式通常由6或7部分內(nèi)容組成,內(nèi)容的取值為數(shù)字或者一些cron表達(dá)式約定的特殊字符,這些特殊字符稱為“通配符”,每一個(gè)通配符分別代指一種值。cron表達(dá)式可以用這樣的表格來表示:
順序 | 取值范圍 | 特殊字符串范圍 |
---|---|---|
秒 | 0~60 | , - * / |
分 | 0-60 | , - * / |
時(shí) | 0-23 | , - * / |
日 | 1-31 | , - * / |
月 | 1-12 / JAN-DEC | , - * ? / L W |
周 | 1-7 / SUN-SAT | , - * ? / L # |
年(可省略) | 1970-2099 | , - * / |
其中通配符的解釋以及作用如下:
通配符 | 代表的值 | 解釋 |
---|---|---|
* | 所有值 | 如:時(shí)字段為*,代表每小時(shí)都觸發(fā) |
? | 不指定值 | 如:周字段為?,代表表達(dá)式不關(guān)心是周幾 |
- | 區(qū)間 | 如:時(shí)字段設(shè)置2-5,代表2,3,4,5點(diǎn)鐘時(shí)都觸發(fā) |
, | 多個(gè)值 | 如:時(shí)字段設(shè)置2,3,5,代表2,3,5點(diǎn)都會(huì)觸發(fā) |
/ | 遞增值 | 如:時(shí)字段設(shè)置0/2,代表每兩個(gè)小時(shí)觸發(fā),時(shí)字段設(shè)置 2/5,代表從2時(shí)開始每隔5小時(shí)觸發(fā)一次 |
L | 最后值 | 如:日字段設(shè)置L,代表本月最后一天 |
W | 最近工作日 | 如:在日字段設(shè)置13W,代表沒約13日最近的那個(gè)工作日觸發(fā)一次 |
# | 序號(hào) | 如:在周字段設(shè)置5#2,代表每月的第二個(gè)周五 |
示例:
每2秒執(zhí)行一次:0/5 ?
每5分鐘執(zhí)行一次:0 0/5 * ?
1分、12分、45分執(zhí)行一次:0 1,12,45 * ?
每天23點(diǎn)59分59秒執(zhí)行一次:59 59 23 ?
每月15號(hào)凌晨3點(diǎn)執(zhí)行一次:0 0 3 15 * ?
每月最后一天12點(diǎn)執(zhí)行一次:0 0 12 L * ?
覺得本文對(duì)你有幫助?請(qǐng)分享給更多人
關(guān)注「編程無界」,提升裝逼技能
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/73250.html
摘要:現(xiàn)在已經(jīng)成為的官方標(biāo)準(zhǔn),如,以及的擴(kuò)展協(xié)議。作者簡介李會(huì)軍,聯(lián)合創(chuàng)始人,關(guān)注團(tuán)隊(duì)協(xié)作領(lǐng)域,致力于用工具解決中小團(tuán)隊(duì)的協(xié)作問題。 Worktile自上線兩年多以來,以良好的用戶體驗(yàn)和穩(wěn)定的服務(wù),獲得了用戶的認(rèn)可和喜愛。截止筆者寫這篇文章的時(shí)候,已經(jīng)有超過10萬家團(tuán)隊(duì)在使用Worktile。作為團(tuán)隊(duì)協(xié)作工具,從技術(shù)上分析首先要解決如下幾個(gè)問題: 基于Web的跨平臺(tái)設(shè)計(jì),讓用戶在任何地方都...
摘要:也是自帶的一個(gè)基于線程池設(shè)計(jì)的定時(shí)任務(wù)類。其每個(gè)調(diào)度任務(wù)都會(huì)分配到線程池中的一個(gè)線程執(zhí)行,所以其任務(wù)是并發(fā)執(zhí)行的,互不影響。 原創(chuàng)不易,如需轉(zhuǎn)載,請(qǐng)注明出處https://www.cnblogs.com/baixianlong/p/10659045.html,否則將追究法律責(zé)任?。?! 一、在JAVA開發(fā)領(lǐng)域,目前可以通過以下幾種方式進(jìn)行定時(shí)任務(wù) 1、單機(jī)部署模式 Timer:jdk中...
摘要:而我這里定時(shí)任務(wù)的觸發(fā)是要通過接口的方式來觸發(fā),所以只用實(shí)現(xiàn)以下的調(diào)度器即可。我這里簡單說下任務(wù)的調(diào)度器,具體的任務(wù)類,觸發(fā)器,任務(wù)什么時(shí)候執(zhí)行是由它決定的。遇到的坑解決方式這個(gè)是因?yàn)椴患嫒莸膯栴},所以使用是不會(huì)出現(xiàn)這個(gè)錯(cuò)誤的。 實(shí)現(xiàn)定時(shí)任務(wù)的幾種方式: 1.使用linux的crontab 優(yōu)點(diǎn): 1.使用方式很簡單,只要在crontab中寫好 2.隨時(shí)可以修改,不需要...
閱讀 2188·2021-11-18 10:02
閱讀 2916·2021-09-04 16:41
閱讀 1219·2019-08-30 15:55
閱讀 1473·2019-08-29 17:27
閱讀 1244·2019-08-29 17:12
閱讀 2619·2019-08-29 15:38
閱讀 2952·2019-08-29 13:02
閱讀 2890·2019-08-29 12:29