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