JavaFX2的ScheduledService类
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属性。