为什么Platform.runLater不检查它当前是否在JavaFX线程上?

时间:2014-06-04 17:04:08

标签: java javafx javafx-8

使用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应用程序线程上运行。

是否有任何理由认为默认实现不会造成这种短路?

3 个答案:

答案 0 :(得分:16)

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

通过短路,您建议先前的任务基本上具有较低的优先级,这可能是不可取的。

答案 1 :(得分:13)

在调用函数时,函数被调用' runLater',我希望它能在以后运行,而不是现在运行。

在我看来,实施是基于它的名称and it's documentation做正确的事情:

  

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

     

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

如果您不希望代码稍后运行,请不要让它稍后运行。这就是你基本上用你的代码完成的。

答案 2 :(得分:0)

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

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

但我保持这个答案有漏洞。看到我建议的答案(用Jython编写,但应该是可以理解的)。假设有人将“点击计数开始编辑”设置为1.假设,更谨慎的是,invokeLaterselectAll之间发生了不可预测的事情。除非你完全确定你没有替代机制,或者绝对确定两个线程的事件和对象完全“解耦”,否则我个人会说避免从JavaFX线程调用runLater

并发总是在等着你。因此,最好小心使用这种技术!