【问题标题】:Why does Platform.runLater not check if it currently is on the JavaFX thread?为什么 Platform.runLater 不检查它当前是否在 JavaFX 线程上?
【发布时间】:2014-07-25 10:57:30
【问题描述】:

在使用 JavaFX 8 时,我们需要通过Platform.runLater 与 GUI 运行交互,否则如果从另一个线程运行它们会抛出异常。

但是,Platform.runLater 的实现从不检查它当前是否在 JavaFX 线程上。

我写了如下方法:

public static void runSafe(final Runnable runnable) {
    Objects.requireNonNull(runnable, "runnable");
    if (Platform.isFxApplicationThread()) {
        runnable.run();
    }
    else {
        Platform.runLater(runnable);
    }
}

这确保它永远不会在非 fx 应用程序线程上运行。

默认实现不做这种短路有什么原因吗?

【问题讨论】:

  • 很高兴在 StackOverflow 上看到好问题和好答案。
  • 我希望将这个方法添加到Platform,因为这是我在 90% 的情况下所要寻找的。​​span>

标签: java javafx javafx-8


【解决方案1】:

runLater 本质上是将您的 Runnable 放入队列中,以便在 FX 线程可用时执行。该方法可以通过非 FX 线程访问。想象一下,其他一些线程已将任务放入runLater 队列,然后再次调用runLater,无论是否来自 FX 线程,都应该将新任务放在该队列的尾部。

由于您提出的短路,以前的任务基本上会具有较低的优先级,这可能是不可取的。

【讨论】:

    【解决方案2】:

    当调用一个函数并且该函数被称为“runLater”时,我希望它稍后运行,而不是现在。

    在我看来,实现是正确的,基于它的名字,and it's documentation:

    在未来某个未指定的时间在 JavaFX 应用程序线程上运行指定的 Runnable。

    此方法可以从任何线程调用,它将 Runnable 发布到事件队列,然后立即返回给调用者。 Runnables 按照它们发布的顺序执行。传入 runLater 方法的 runnable 将在任何 Runnable 传入后续调用 runLater 之前执行

    如果您不希望代码稍后运行,请不要要求稍后运行。这就是您对代码所做的基本工作。

    【讨论】:

      【解决方案3】:

      我看到人们偶尔在 Swing 的 EDT 中调用EventQueue.invokeLater...根据佳能,这是一种合法的技术。所以这与 JavaFX 中的情况相同,除非我弄错了。

      不过,我个人对这种技术持怀疑态度。请参阅this question:所选答案使用invokeLater,因为selectAll() 需要在调用之前让所有当前EDT 事件自行完成:此解决方案确实确保selectAll 不能在此处发生其他EDT 代码之前运行.

      但我认为,这个答案存在漏洞。请参阅我建议的答案(用 Jython 编写,但应该可以理解)。假设有人将“开始编辑的点击次数”设置为 1。假设更令人担忧的是,invokeLaterselectAll 之间发生了不可预测的事情。除非您绝对确定根本没有替代机制,或者绝对确定两个线程的事件和对象完全“解耦”,否则我个人会说避免从 JavaFX 线程调用 runLater

      并发总是等着咬你。因此,最好谨慎使用此类技术!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-02
        • 2012-07-09
        • 2012-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-21
        相关资源
        最近更新 更多