JavaFX定期后台任务

我尝试在JavaFX应用程序后台线程中定期运行,这会修改某些GUI属性。

我想我知道如何使用javafx.concurrent TaskService类,并且不知道如何在不使用Thread#sleep()方法的情况下运行这样的周期性任务。 这将是很好,如果我可以使用ExecutorExecutors制造方法( Executors.newSingleThreadScheduledExecutor()

我试图每5秒运行一次Runnable ,这会重新启动javafx.concurrent.Service但是会立即挂起,因为service.restart或者甚至是service.getState()被调用。

所以最后我使用Executors.newSingleThreadScheduledExecutor() ,每5秒触发一次RunnableRunnable使用以下命令运行另一个Runnable

 Platform.runLater(new Runnable() { //here i can modify GUI properties } 

它看起来非常讨厌:(有没有更好的方式来使用TaskService类来做到这一点?

你可以使用时间线来处理:

 Timeline fiveSecondsWonder = new Timeline(new KeyFrame(Duration.seconds(5), new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { System.out.println("this is called every 5 seconds on UI thread"); } })); fiveSecondsWonder.setCycleCount(Timeline.INDEFINITE); fiveSecondsWonder.play(); 

对于后台进程(对UI没有任何影响),你可以使用旧的java.util.Timer

 new Timer().schedule( new TimerTask() { @Override public void run() { System.out.println("ping"); } }, 0, 5000); 

这是一个使用Java 8和ReactFX的解决scheme。 假设您要定期重新计算Label.textProperty()的值。

 Label label = ...; EventStreams.ticks(Duration.ofSeconds(5)) // emits periodic ticks .supplyCompletionStage(() -> getStatusAsync()) // starts a background task on each tick .await() // emits task results, when ready .subscribe(label::setText); // performs label.setText() for each result CompletionStage<String> getStatusAsync() { return CompletableFuture.supplyAsync(() -> getStatusFromNetwork()); } String getStatusFromNetwork() { // ... } 

与Sergey的解决scheme相比,您不需要专门从networking获取状态,而是使用共享线程池。

我会更喜欢PauseTransition:

  PauseTransition wait = new PauseTransition(Duration.seconds(5)); wait.setOnFinished((e) -> { /*YOUR METHOD*/ wait.playFromStart(); }); wait.play();