JavaFX的Swing计时器替代和线程管理的区别

时间:2014-03-18 17:58:44

标签: multithreading swing timer javafx javafx-8

对JavaFX使用Swing计时器是否安全?还是Swing有一个特殊的选择? JavaFX和Swing之间的线程管理有何不同?

事实上,我很想知道JavaFX的 Swing Timer SwingUtilities.invokeLater()invodeAndWait()的等价物。

顺便说一句,如果我们在JavaFX中使用一些Swing组件呢?我们应该使用两个并行的定时器/线程来更新这些组件吗?

1 个答案:

答案 0 :(得分:8)

JavaFX等效于SwingUtilities.invokeLater()

Platform.runLater(java.lang.Runnable runnable)

另见JavaFx response to SwingUtilities.invokeLater

JavaFX等效于invokeAndWait()

公共JavaFX API故意不在Platform.runLater上公开invokeAndWait调用,因为它很容易使用它自动死锁,所以只要你确切知道自己在做什么,就可以使用下面的代码。

final FutureTask query = new FutureTask(new Callable() {
    @Override
    public Object call() throws Exception {
        return queryPassword();
    }
});
Platform.runLater(query);
System.out.println(query.get()); // the get blocks until the query FutureTask completes.

另见Return result from javafx platform runlater

JavaFX等效于javax.swing.Timer

使用Timeline。以下内容将更新每秒显示日期的标签:

DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Label dateLabel = new Label();
Timeline timeline = new Timeline(
    new KeyFrame(
      Duration.ZERO,
      actionEvent -> dateLabel.set(dateFormat.format(new Date()))
    ),
    new KeyFrame(
      Duration.seconds(1)
    )
);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();

另请参阅基于时间轴的How to update the label box every 2 seconds in java fx?答案。

  

如果我们在JavaFX中使用一些Swing组件?我们应该使用两个并行的定时器/线程来更新这些组件吗?

我认为不是,取决于应用程序,但通常会优先选择应用程序的单个计时器。这是一种专门的案例。通常,如果您在Timer上发生了一些异步过程,您希望它一次性发生,因此Timer会触发,进行一些处理,然后将结果分流回GUI。当您混合使用两个UI框架时,它会更复杂一些,因为您希望同时或在同一渲染帧中更新两个框架。

为了估算这一点,我建议您只使用普通java.util.Timer而不是javax.swing.Timer,或者如果您需要更多灵活性,请使用ScheduledExectorService。然后,在TimerTask或预定Runnable中,执行处理逻辑,处理完成后,调用Platform.runLater 并单独调用 SwingUtilities.invokeLater以分流处理结果返回JavaFX或Swing组件。

当然,您应该考虑混合两个这样的框架并处理潜在的线程并发症是值得的。如果您能够使用单个框架并依赖最适合该框架的并发方法,我认为这将是一种首选方法。

  

JavaFX和Swing之间的线程管理有什么区别?

从用户的角度来看,它非常相似。 JavaFX和Swing都是用于应用程序层UI处理的单线程框架。 JavaFX的所有用户代码都在JavaFX应用程序线程上运行。此外,任何可能修改活动场景图(舞台上显示的节点)的代码都必须在JavaFX应用程序线程上运行。这些规则类似于Swing编程中线程管理的本质。

默认情况下,Java 8初始版本中的JavaFX应用程序线程和Swing线程是不同的。所以:

  1. 要从JavaFX应用程序线程更新Swing组件,请使用Platform.runLater将处理从JavaFX线程切换到Swing线程。
  2. 要从Swing线程更新JavaFX节点,请使用SwingUtilities.invokeLater将处理从Swing线程切换到JavaFX线程。
  3. Java平台的未来版本可能包含Swing和JavaFX的统一应用程序线程。

    请注意,库代码中使用的内部线程实现在Swing和JavaFX之间有所不同。 JavaFX将使用可以在自己的线程上运行的不同硬件和软件渲染管道。但是,这个内部实现细节完全隐藏在应用程序程序员之外。

    参考文档

    Oracle的

    Concurrency in JavaFX Tutorial。特别是,请参阅TaskService上有关管理JavaFX后台操作的部分,这些主题未在此答案中明确讨论过。