[英]Java library class to handle scheduled execution of “callbacks”?
我的程序有一個組件——稱為調度程序——它允許其他組件注冊它們想要被回調的時間點。 這應該很像 Unix cron 服務,即您告訴調度程序“在每整整一小時后十分鍾通知我”。
我意識到 Java 中沒有真正的回調。
這是我的方法,是否有一個圖書館已經做了這些事情? 也可以隨意提出改進建議。
注冊對調度程序通行證的調用:
在啟動時,或在新的注冊請求之后,調度程序以當前系統時間的日歷 object 開始,並檢查數據庫中是否有任何條目與該時間點匹配。 如果有,則執行它們並重新開始該過程。 如果沒有,日歷 object 中的時間會增加一秒並重新檢查主條目。 如此重復,直到有一個或多個匹配項。 (離散事件模擬)
然后調度程序將記住該時間戳,每秒睡眠和喚醒以檢查它是否已經存在。 如果它碰巧醒來並且時間已經過去,它會重新開始,同樣如果時間到了並且作業已經執行。
編輯:感謝您將我指向 Quartz。 然而,我正在尋找更小的東西。
查找石英
如果您的對象確切地知道它們希望執行的各個時間點,那么您可以使用java.util.concurrent.ScheduledExecutorService
。 然后他們簡單地調用:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
long timeToExecute = ... //read from DB? use CronTrigger?
long delayToExecution = timeToExecute - System.currentTimeMillis();
scheduler.schedule(aRunnable, delayToExecution, TimeUnit.MILLISECONDS);
如果您希望調度程序本身處理諸如“每 5 秒執行一次”之類的功能,或者您想要圍繞錯過執行的復雜行為,或者執行審計跟蹤的持久性,您只需要使用Quartz
。
您實際上可以簡單地重復使用 Quartz 的CronTrigger
class 來獲得“下一個執行時間”。 class 是完全獨立的,不依賴於從Quartz
“上下文”中調用。 一旦您將下一個執行時間設置為Date
或long
,您就可以像上面一樣使用 Java ScheduledExecutorService
Quartz是該領域的大而明顯的強者,但也有一些替代品可供探索。
Cron4j是一個足夠好的庫,它比 Quartz 更輕量級。 它提供了良好的文檔,並會做你想做的事。
可能更有趣的是,如果您想使用更適合 Java 並發庫(特別是 Executors 和 ScheduledExecutors)的庫,那么HA-JDBC有一個CronExecutorService接口,由其CronThreadPoolExecutor實現。 現在,有趣的是,它依賴於 Quartz(提供 CronExpression 類),但我發現兩者一起工作比單獨使用 Quartz 更好。 如果您不想要大的依賴關系,可以很容易地從 Quartz 和 HA-JDBC 中提取少量的類來實現這一點。
因為你想要更小的東西(剛剛注意到你的編輯),所以從 Quartz 中獲取 CronExpression,以及我上面提到的兩個 HA-JDBC 類。 這樣就可以了。
如果您的需求很簡單,請考慮使用java.util.Timer :
public class TimerDemo {
public static void main(String[] args) {
// non-daemon threads prevent termination of VM
final boolean isDaemon = false;
Timer timer = new Timer(isDaemon);
final long threeSeconds = 3 * 1000;
final long delay = 0;
timer.schedule(new HelloTask(), delay, threeSeconds);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, 1);
Date oneMinuteFromNow = calendar.getTime();
timer.schedule(new KillTask(timer), oneMinuteFromNow);
}
static class HelloTask extends TimerTask {
@Override
public void run() {
System.out.println("Hello");
}
}
static class KillTask extends TimerTask {
private final Timer timer;
public KillTask(Timer timer) {
this.timer = timer;
}
@Override
public void run() {
System.out.println("Cancelling timer");
timer.cancel();
}
}
}
如前所述,如果您需要, java.util.concurrent的ExecutorService提供了更豐富的 API。
我強烈推薦cron4j (已經提到過)而不是 Quartz,除非你絕對需要 Quartz 的一些更高級和復雜的特性。 Cron4j 很好地專注於它應該做的事情,擁有不錯的文檔,並且不是一個廚房水槽解決方案。
可能更有趣的是,如果您想使用更適合 Java 並發庫(特別是 Executors 和 ScheduledExecutors)的庫,那么 HA-JDBC 有一個 CronExecutorService 接口,由其 CronThreadPoolExecutor 實現。 現在,有趣的是,它依賴於 Quartz(提供 CronExpression 類),但我發現兩者一起工作比單獨使用 Quartz 更好。 如果您不想要大的依賴關系,可以很容易地從 Quartz 和 HA-JDBC 中提取少量的類來實現這一點。
我只是想說我嘗試提取這些類,並且成功了:我需要這三個類:
我只需要做這些小調整:
我很高興我沒有陷入糾纏不清的依賴關系中。 祝賀 class 作者!
它一直像冠軍一樣工作。
通常推薦使用Quartz 調度器。
不敢相信 java.util.Timer 被選為答案。 石英確實是一個更好的選擇。
與 java.util.Timer 相比,石英的一大優勢在於,使用石英,作業可以存儲在數據庫中。 結果,一個 jvm 可以調度,另一個可以執行。 此外(顯然)該請求在 jvm 重新啟動后仍然存在。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.