ScheduledService類位於javafx.concurrent包下面,是用來定時執行循環任務的。
ScheduledService繼承自Service類,Service類會在成功執行任務後自動重新開始下一次執行,在一定的條件下及時執行失敗了也會重新執行的。一個ScheduledService實例最初是READY狀態,調用start()或者restart()方法後就變成SCHEDULED狀態,然後持續該狀態由delay指定的時長。
再進入RUNNING狀態後ScheduledService就會開始執行它的Task,成功執行一次以後ScheduledService會變成SUCCEDED狀態,然後變成READY,然後又開始SCHEDULED。在這個狀態呆多久,取決於轉變爲RUNNING的時間、當前的時間和變量period值。簡單點說,period定義了從一個Task開始到下一個的時長。如果執行完了period還是沒到期,ScheduledService保持SCHEDULED狀態等period耗完;反之,如果還沒執行完period就到了,ScheduledService就立即開始RUNNINNG狀態。
當在RUNNING的時候,ScheduledService拋異常了或者由於其他原因進入了FAILED狀態,ScheduledService到底結束呢還是重新開始呢,取決於backoffStrategy
, restartOnFailure 和
maximumFailureCount的值:
如果異常發生了而且restartonfailure是false,ScheduledService就進入FAILED停止了。只有調用restart方法才能重新運行;
如果異常發生了而restartonfailure是true,ScheduledService可能會自動重啓。首先根據策略backoffstrategy的結果設置cumulativePeriod值,這樣失敗後會等待很久很久來重啓;執行成功後cumulativePeriod就又變回period值;ScheduledService定義了幾個靜態策略,比如EXPONENTIAL_BACKOFF_STRATEGY 和 LOGARITHMIC_BACKOFF_STRATEGY,默認是後者。當maximumfailurecount達到後就和restartonfailure爲false一樣了。
如果執行過程中period或者delay改變了,它們將影響下一次執行。ScheduledService的典型應用是循環調用,比如以一定間隔ping一臺主機:
ScheduledService<Document> svc = new ScheduledService<Document>() {
protected Task<Document> createTask() {
return new Task<Document>() {
protected Document call() {
// 連接主機
// 獲取信息
// 轉換成document
return document;
}
};
}
};
svc.setPeriod(Duration.seconds(1));
這個任務每一秒執行一下。
不過這個類對於時間沒什麼太好的觀念:不準確。一個非常忙的線程可能會引起比較嚴重的延遲。所以如果period或者delay的值很小可能不太準確,不過超過幾百毫秒一般就相當可靠了。
ScheduledService的默認period和delay都是0,這樣認爲會立即一下一下地執行。想要取到執行的結果可以用lastValue屬性。