我想从JavaFX应用程序定期执行任务。该任务从远程流中提取数据。
虽然我知道我可以按照以下建议使用定时器:
JavaFX periodic background task
我相信这应该可以使用JavaFX Service对象来完成。在Javadoc中提到了指定一个自定义执行器(这里会想到ScheduledThreadPoolExecutor),但是如何指定周期和延迟呢?理想情况下,这将使用服务的常规启动,重置,重启和状态绑定......
public class MyFirstLineService extends Service<String> {
private StringProperty url = new SimpleStringProperty(this, "url");
public final void setUrl(String value) { url.set(value); }
public final String getUrl() { return url.get(); }
public final StringProperty urlProperty() { return url; }
public MyFirstLineService() {
setExecutor(new ScheduledThreadPoolExecutor());
}
protected Task createTask() {
final String _url = getUrl();
return new Task<String>() {
protected String call() throws Exception {
URL u = new URL(_url);
BufferedReader in = new BufferedReader(
new InputStreamReader(u.openStream()));
String result = in.readLine();
in.close();
return result;
}
};
}
}
答案 0 :(得分:3)
在JavaFX issue tracker - RT18702。
中请求了ScheduledService跟踪器包含source for a preliminary implementation,但尚未纳入2.2分支。如果需要,您可以查看该来源,看看它是否有助于改进您的解决方案。
答案 1 :(得分:2)
我找到了一种方法来做到这一点,建立在上面sarcan的评论......
可以创建一个时间轴对象,通常用于动画UI元素,作为在FX应用程序线程上运行的计时器。使用它可以重新启动Service对象,然后Service对象在后台线程上执行长时间运行操作,同时通过FX Application Thread绑定保留属性访问和更新。
例如:
final MyFirstLineService svc = new MyFirstLineService();
final Duration oneFrameAmt = Duration.seconds(5);
final KeyFrame oneFrame = new KeyFrame(oneFrameAmt,
new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent evt) {
svc.restart();
}
});
Timeline timer = TimelineBuilder.create()
.cycleCount(Animation.INDEFINITE)
.keyFrames(oneFrame)
.build();
timer.playFromStart();
答案 2 :(得分:1)
遇到同样的问题。 ScheduledThreadPoolExecutor
的示例可能是:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
Service s = new Service(){
@Override
protected Task<String> createTask() {
return new Task<String>() {
@Override
protected String call() throws Exception {
// code...
}
};
}
}
// created tasks shall be run in thread pool
s.setExecutor(executor);
// start the service the first time
s.start();
// restart the service every 5 seconds
s.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
// need runLater here since trigger needs to be in the javaFX thread
Platform.runLater(new Runnable() {
@Override
public void run() {
checker.restart();
}
});
}
}, 0, 5, TimeUnit.SECONDS);
}
可以使用Timer
解决但是您丢失了JavaFX数据绑定功能(如您所述)。期待Java8!