java.util.Timer
是 JDK 1.3 開(kāi)始就已經(jīng)支持的一種定時(shí)任務(wù)的實(shí)現(xiàn)方式。Timer
內(nèi)部使用一個(gè)叫做 TaskQueue
的類(lèi)存放定時(shí)任務(wù),它是一個(gè)基于最小堆實(shí)現(xiàn)的優(yōu)先級(jí)隊(duì)列。TaskQueue
會(huì)按照任務(wù)距離下一次執(zhí)行時(shí)間的大小將任務(wù)排序,保證在堆頂?shù)娜蝿?wù)最先執(zhí)行。這樣在需要執(zhí)行任務(wù)時(shí),每次只需要取出堆頂?shù)娜蝿?wù)運(yùn)行即可!Timer
使用起來(lái)比較簡(jiǎn)單,通過(guò)下面的方式我們就能創(chuàng)建一個(gè) 1s 之后執(zhí)行的定時(shí)任務(wù)。//?示例代碼:
TimerTask?task?=?new?TimerTask()?{
????public?void?run()?{
????????System.out.println("當(dāng)前時(shí)間:?"? ?new?Date()? ?"n"?
????????????????"線(xiàn)程名稱(chēng):?"? ?Thread.currentThread().getName());
????}
};
System.out.println("當(dāng)前時(shí)間:?"? ?new?Date()? ?"n"?
????????"線(xiàn)程名稱(chēng):?"? ?Thread.currentThread().getName());
Timer?timer?=?new?Timer("Timer");
long?delay?=?1000L;
timer.schedule(task,?delay);
//輸出:
當(dāng)前時(shí)間:?Fri?May?28?15:18:47?CST?2021n線(xiàn)程名稱(chēng):?main
當(dāng)前時(shí)間:?Fri?May?28?15:18:48?CST?2021n線(xiàn)程名稱(chēng):?Timer
不過(guò)其缺陷較多,比如一個(gè) Timer
一個(gè)線(xiàn)程,這就導(dǎo)致 Timer
的任務(wù)的執(zhí)行只能串行執(zhí)行,一個(gè)任務(wù)執(zhí)行時(shí)間過(guò)長(zhǎng)的話(huà)會(huì)影響其他任務(wù)(性能非常差),再比如發(fā)生異常時(shí)任務(wù)直接停止(Timer
只捕獲了 InterruptedException
)。Timer
類(lèi)上的有一段注釋是這樣寫(xiě)的:?*?This?class?does?not?offer?real-time?guarantees:?it?schedules
?*?tasks?using?the?<tt>Object.wait(long)tt>?method.
?*Java?5.0?introduced?the?{@code?java.util.concurrent}?package?and
?*?one?of?the?concurrency?utilities?therein?is?the?{@link
?*?java.util.concurrent.ScheduledThreadPoolExecutor
?*?ScheduledThreadPoolExecutor}?which?is?a?thread?pool?for?repeatedly
?*?executing?tasks?at?a?given?rate?or?delay.??It?is?effectively?a?more
?*?versatile?replacement?for?the?{@code?Timer}/{@code?TimerTask}
?*?combination,?as?it?allows?multiple?service?threads,?accepts?various
?*?time?units,?and?doesn't?require?subclassing?{@code?TimerTask}?(just
?*?implement?{@code?Runnable}).??Configuring?{@code
?*?ScheduledThreadPoolExecutor}?with?one?thread?makes?it?equivalent?to
?*?{@code?Timer}.
大概的意思就是:ScheduledThreadPoolExecutor
支持多線(xiàn)程執(zhí)行定時(shí)任務(wù)并且功能更強(qiáng)大,是 Timer
的替代品。ScheduledExecutorService
是一個(gè)接口,有多個(gè)實(shí)現(xiàn)類(lèi),比較常用的是 ScheduledThreadPoolExecutor
。ScheduledThreadPoolExecutor
本身就是一個(gè)線(xiàn)程池,支持任務(wù)并發(fā)執(zhí)行。并且,其內(nèi)部使用 DelayQueue
作為任務(wù)隊(duì)列。//?示例代碼:
TimerTask?repeatedTask?=?new?TimerTask()?{
????@SneakyThrows
????public?void?run()?{
????????System.out.println("當(dāng)前時(shí)間:?"? ?new?Date()? ?"n"?
????????????????"線(xiàn)程名稱(chēng):?"? ?Thread.currentThread().getName());
????}
};
System.out.println("當(dāng)前時(shí)間:?"? ?new?Date()? ?"n"?
????????"線(xiàn)程名稱(chēng):?"? ?Thread.currentThread().getName());
ScheduledExecutorService?executor?=?Executors.newScheduledThreadPool(3);
long?delay??=?1000L;
long?period?=?1000L;
executor.scheduleAtFixedRate(repeatedTask,?delay,?period,?TimeUnit.MILLISECONDS);
Thread.sleep(delay? ?period?*?5);
executor.shutdown();
//輸出:
當(dāng)前時(shí)間:?Fri?May?28?15:40:46?CST?2021n線(xiàn)程名稱(chēng):?main
當(dāng)前時(shí)間:?Fri?May?28?15:40:47?CST?2021n線(xiàn)程名稱(chēng):?pool-1-thread-1
當(dāng)前時(shí)間:?Fri?May?28?15:40:48?CST?2021n線(xiàn)程名稱(chēng):?pool-1-thread-1
當(dāng)前時(shí)間:?Fri?May?28?15:40:49?CST?2021n線(xiàn)程名稱(chēng):?pool-1-thread-2
當(dāng)前時(shí)間:?Fri?May?28?15:40:50?CST?2021n線(xiàn)程名稱(chēng):?pool-1-thread-2
當(dāng)前時(shí)間:?Fri?May?28?15:40:51?CST?2021n線(xiàn)程名稱(chēng):?pool-1-thread-2
當(dāng)前時(shí)間:?Fri?May?28?15:40:52?CST?2021n線(xiàn)程名稱(chēng):?pool-1-thread-2
不論是使用 Timer
還是 ScheduledExecutorService
都無(wú)法使用 Cron 表達(dá)式指定任務(wù)執(zhí)行的具體時(shí)間。@Scheduled
注解即可定義定時(shí)任務(wù),非常方便!/**
?* cron:使用Cron表達(dá)式。?每分鐘的1,2秒運(yùn)行
?*/
@Scheduled(cron?=?"1-2?*?*?*?*???")
public?void?reportCurrentTimeWithCronExpression()?{
??log.info("Cron?Expression:?The?time?is?now?{}",?dateFormat.format(new?Date()));
}
我在大學(xué)那會(huì)做的一個(gè) SSM 的企業(yè)級(jí)項(xiàng)目,就是用的 Spring Task 來(lái)做的定時(shí)任務(wù)。并且,Spring Task 還是支持 Cron 表達(dá)式 的。Cron 表達(dá)式主要用于定時(shí)作業(yè)(定時(shí)任務(wù))系統(tǒng)定義執(zhí)行時(shí)間或執(zhí)行頻率的表達(dá)式,非常厲害,你可以通過(guò) Cron 表達(dá)式進(jìn)行設(shè)置定時(shí)任務(wù)每天或者每個(gè)月什么時(shí)候執(zhí)行等等操作。咱們要學(xué)習(xí)定時(shí)任務(wù)的話(huà),Cron 表達(dá)式是一定是要重點(diǎn)關(guān)注的。推薦一個(gè)在線(xiàn) Cron 表達(dá)式生成器:http://cron.qqe2.com/ 。但是,Spring 自帶的定時(shí)調(diào)度只支持單機(jī),并且提供的功能比較單一。之前寫(xiě)過(guò)一篇文章:《5 分鐘搞懂如何在 Spring Boot 中 Schedule Tasks》 ,不了解的小伙伴可以參考一下。Spring Task 底層是基于 JDK 的 ScheduledThreadPoolExecutor
線(xiàn)程池來(lái)實(shí)現(xiàn)的。優(yōu)缺點(diǎn)總結(jié):Java
寫(xiě)成。Quartz
可以說(shuō)是 Java 定時(shí)任務(wù)領(lǐng)域的老大哥或者說(shuō)參考標(biāo)準(zhǔn),其他的任務(wù)調(diào)度框架基本都是基于 Quartz
開(kāi)發(fā)的,比如當(dāng)當(dāng)網(wǎng)的elastic-job
就是基于quartz
二次開(kāi)發(fā)之后的分布式調(diào)度解決方案。使用 Quartz
可以很方便地與 Spring
集成,并且支持動(dòng)態(tài)添加任務(wù)和集群。但是,Quartz
使用起來(lái)也比較麻煩,API 繁瑣。并且,Quzrtz
并沒(méi)有內(nèi)置 UI 管理控制臺(tái),不過(guò)你可以使用 quartzui 這個(gè)開(kāi)源項(xiàng)目來(lái)解決這個(gè)問(wèn)題。另外,Quartz
雖然也支持分布式任務(wù)。但是,它是在數(shù)據(jù)庫(kù)層面,通過(guò)數(shù)據(jù)庫(kù)的鎖機(jī)制做的,有非常多的弊端比如系統(tǒng)侵入性嚴(yán)重、節(jié)點(diǎn)負(fù)載不均衡。有點(diǎn)偽分布式的味道。優(yōu)缺點(diǎn)總結(jié):Spring
集成,并且支持動(dòng)態(tài)添加任務(wù)和集群。Elastic-Job
是當(dāng)當(dāng)網(wǎng)開(kāi)源的一個(gè)基于Quartz
和ZooKeeper
的分布式調(diào)度解決方案,由兩個(gè)相互獨(dú)立的子項(xiàng)目 Elastic-Job-Lite
和 Elastic-Job-Cloud
組成,一般我們只要使用 Elastic-Job-Lite
就好。ElasticJob
支持任務(wù)在分布式場(chǎng)景下的分片和高可用、任務(wù)可視化管理等功能。Elastic-Job
沒(méi)有調(diào)度中心這一概念,而是使用 ZooKeeper
作為注冊(cè)中心,注冊(cè)中心負(fù)責(zé)協(xié)調(diào)分配任務(wù)到不同的節(jié)點(diǎn)上。Elastic-Job 中的定時(shí)調(diào)度都是由執(zhí)行器自行觸發(fā),這種設(shè)計(jì)也被稱(chēng)為去中心化設(shè)計(jì)(調(diào)度和處理都是執(zhí)行器單獨(dú)完成)。@Component
@ElasticJobConf(name?=?"dayJob",?cron?=?"0/10?*?*?*?*??",?shardingTotalCount?=?2,
????????shardingItemParameters?=?"0=AAAA,1=BBBB",?description?=?"簡(jiǎn)單任務(wù)",?failover?=?true)
public?class?TestJob?implements?SimpleJob?{
????@Override
????public?void?execute(ShardingContext?shardingContext)?{
????????log.info("TestJob任務(wù)名:【{}】, 片數(shù):【{}】, param=【{}】",?shardingContext.getJobName(),?shardingContext.getShardingTotalCount(),
????????????????shardingContext.getShardingParameter());
????}
}
相關(guān)地址:Spring
集成、支持分布式、支持集群、性能不錯(cuò)XXL-JOB
于 2015 年開(kāi)源,是一款優(yōu)秀的輕量級(jí)分布式任務(wù)調(diào)度框架,支持任務(wù)可視化管理、彈性擴(kuò)容縮容、任務(wù)失敗重試和告警、任務(wù)分片等功能,XXL-JOB
官網(wǎng)介紹,其解決了很多 Quartz
的不足。XXL-JOB
的架構(gòu)設(shè)計(jì)如下圖所示:XXL-JOB
由 調(diào)度中心 和 執(zhí)行器 兩大部分組成。調(diào)度中心主要負(fù)責(zé)任務(wù)管理、執(zhí)行器管理以及日志管理。執(zhí)行器主要是接收調(diào)度信號(hào)并處理。另外,調(diào)度中心進(jìn)行任務(wù)調(diào)度時(shí),是通過(guò)自研 RPC 來(lái)實(shí)現(xiàn)的。不同于 Elastic-Job
的去中心化設(shè)計(jì), XXL-JOB
的這種設(shè)計(jì)也被稱(chēng)為中心化設(shè)計(jì)(調(diào)度中心調(diào)度多個(gè)執(zhí)行器執(zhí)行任務(wù))。和 Quzrtz
類(lèi)似 XXL-JOB
也是基于數(shù)據(jù)庫(kù)鎖調(diào)度任務(wù),存在性能瓶頸。不過(guò),一般在任務(wù)量不是特別大的情況下,沒(méi)有什么影響的,可以滿(mǎn)足絕大部分公司的要求。不要被 XXL-JOB
的架構(gòu)圖給嚇著了,實(shí)際上,我們要用 XXL-JOB
的話(huà),只需要重寫(xiě) IJobHandler
自定義任務(wù)執(zhí)行邏輯就可以了,非常易用!@JobHandler(value="myApiJobHandler")
@Component
public?class?MyApiJobHandler?extends?IJobHandler?{
????@Override
????public?ReturnT?execute(String?param)?throws?Exception? {
????????//......
????????return?ReturnT.SUCCESS;
????}
}
還可以直接基于注解定義任務(wù)。@XxlJob("myAnnotationJobHandler")
public?ReturnT?myAnnotationJobHandler(String?param)?throws?Exception? {
??//......
??return?ReturnT.SUCCESS;
}
摘要:高壓磁電機(jī)是航空活塞發(fā)動(dòng)機(jī)點(diǎn)火系統(tǒng)中的核心部件,磁電機(jī)內(nèi)定時(shí)和發(fā)動(dòng)機(jī)外定時(shí)關(guān)乎發(fā)動(dòng)機(jī)的正常運(yùn)轉(zhuǎn)。沒(méi)有準(zhǔn)確的定時(shí),發(fā)動(dòng)機(jī)可能無(wú)法正常啟動(dòng)或者異常抖動(dòng)。此外,點(diǎn)火系統(tǒng)的檢查亦關(guān)系到發(fā)動(dòng)機(jī)能否持續(xù)正常工作?;诖?詳細(xì)分...
關(guān)鍵字: 磁電機(jī) 定時(shí) 點(diǎn)火系統(tǒng)深圳2022年7月18日 /美通社/ -- 近期,招商信諾人壽推出"健康有諾 財(cái)富有招"系列活動(dòng),以身體健康、財(cái)富健康、家庭健康、社交健康和職場(chǎng)健康5大維度為核心,邀請(qǐng)超百位各界權(quán)威專(zhuān)家,橫跨20余個(gè)...
關(guān)鍵字: VIP 互聯(lián)網(wǎng) 定時(shí) 網(wǎng)絡(luò)上海2022年7月6日 /美通社/ -- 近日,德國(guó)萊茵TUV大中華區(qū)(以下簡(jiǎn)稱(chēng)"TUV萊茵")作為主要參編單位出席了在上海舉辦的"零碳冷鏈園區(qū)...
關(guān)鍵字: 供應(yīng)鏈 定時(shí) 建模 操作系統(tǒng)這個(gè)夏天,讓我們?cè)谛前涂酥鼐郏? 上海2022年6月29日 /美通社/ -- "終于又能在星巴克舒舒服服地坐著,和咖啡師小伙伴一邊聊天,一邊品嘗我最?lèi)?ài)的手沖咖啡了!"在興業(yè)太古匯工作的李小姐...
關(guān)鍵字: BSP 定時(shí) 測(cè)溫 沉浸式體驗(yàn)北京2022年5月9日 /美通社/ -- 隨著北京出現(xiàn)新一輪疫情,政府部門(mén)頒布了全域禁止堂食的要求。北京凱賓斯基飯店一方面強(qiáng)化疫情防控,嚴(yán)格執(zhí)行測(cè)溫、掃碼、核酸查驗(yàn)等防控措施;另一方面進(jìn)一步提升餐飲品質(zhì)服務(wù),利用近年來(lái)培...
關(guān)鍵字: 微信小程序 定時(shí) BSP 新風(fēng)系統(tǒng)摘 要:文中研發(fā)一款多功能智能寵物喂食系統(tǒng),該系統(tǒng)主要功能包括自定義實(shí)時(shí)喂食狀態(tài)、用戶(hù)喂食時(shí)間,語(yǔ)音信息提示寵物進(jìn)食,殘留物自動(dòng)清理等。系統(tǒng)解決了目前市場(chǎng)上寵物自動(dòng)喂食系統(tǒng)無(wú)法對(duì)殘留物進(jìn)行清理和人機(jī)交互不友好等問(wèn)題
關(guān)鍵字: 自動(dòng)寵物喂食 殘食清理 語(yǔ)音提示 定時(shí)在springboot項(xiàng)目中,可以通過(guò)@EnableScheduling注解和@Scheduled注解實(shí)現(xiàn)定時(shí)任務(wù),也可以通過(guò)SchedulingConfigurer接口來(lái)實(shí)現(xiàn)定時(shí)任務(wù)。但是這兩種方式不能動(dòng)態(tài)添加、刪除、...
關(guān)鍵字: 定時(shí)