【问题标题】:JavaFX: Can a node's tranforms be safely manipulated from a non-UI thread? [duplicate]JavaFX:可以从非 UI 线程安全地操作节点的转换吗? [复制]
【发布时间】:2019-12-22 18:20:48
【问题描述】:

我一直在使用 javafx 开发机器人模拟器。它使用一个单独的线程来计算机器人及其每个部件在每次增量后应该在哪里。 UI 的实际更新是通过调用Platform.runLater() 来处理的。

这是一个名为 leftFinger 的节点(在本例中为 Rectangle)如何被操作的示例:

首先,在 Controller 类中,创建一个 Translate 对象并将其添加到节点的变换中:

leftFingerTranslateTransform = new Translate(0, 0);
leftFinger.getTransforms().add(leftFingerTranslateTransform);

然后,在传递给Platform.runLater() 的方法中执行以下操作:

leftFingerTranslateTransform.setY(-40.0 * (armScale - 1.0));
leftFingerTranslateTransform.setX(fingerPos);

上面的效果很好。

有一次,我不小心将一些节点重新定位代码(即对 Tranlate.setX()Translate.setY() 的调用)放入了一个由非 UI 线程调用的方法中,而没有调用 @987654328 @。令我惊讶的是,这行得通,没有任何问题。但我想知道这是否引起问题。

我对 javafx 和多线程信息的搜索使我相信 UI 不能(或至少不应该)直接从非 UI 线程进行操作。通过实验,我发现尝试从非 UI 线程向场景添加节点会导致抛出异常,但操作(即更改属性)属于节点的变换不会。

我的问题是:属于节点的转换是否可以安全地从非 UI 线程更改其属性(不使用 Platform.runLater())?

【问题讨论】:

  • “……我想知道这是否会导致问题。”是的。线程问题因不会立即引起明显问题而臭名昭著,但最终肯定会导致问题。
  • "节点对象可以在任何线程上构建和修改,只要它们尚未附加到正在显示的窗口中的场景。应用程序必须将节点附加到这样的场景或修改它们在 JavaFX 应用程序线程上" – Node。这条规则没有例外,尽管有些对象限制性更强,只能在 FX 线程上构造或修改(例如 Stage)。
  • Group 的边界取决于子元素的变换。因此,对转换的更新可能会触发布局传递。我没有调查,如果这会导致问题,但我的可能性很高......

标签: java multithreading javafx


【解决方案1】:

从非 UI 线程更改节点上的变换,当节点附加到活动场景时,可能会导致竞争条件等问题。

不要这样做。

解释

来自维基百科race conditions

当应用程序依赖于进程或线程的顺序或时间来使其正常运行时,软件中就会出现竞争条件。与电子产品一样,存在导致无效执行和错误的关键竞争条件。当进程或线程依赖于某些共享状态时,通常会发生严重的竞争条件。对共享状态的操作是必须互斥的关键部分。不遵守此规则可能会破坏共享状态。

这里,共享状态是从它们派生的变换和东西的列表(例如场景的布局)。

来自Node Javadoc,在 cmets 中由 Slaw 链接:

节点对象可以在任何线程上构造和修改,只要它们尚未附加到正在显示的窗口中的场景。应用程序必须将节点附加到这样的场景或在 JavaFX 应用程序线程上修改它们

它不安全的原因是因为 JavaFX UI 线程在定时脉冲上运行(请参阅JavaFX architecture doc 以了解这一点),与任何非 UI 线程同时运行。在定时脉冲期间,渲染场景、应用 CSS、应用变换、更新动画属性等。因此,如果您在非 UI 线程上修改变换,同时它们在 UI 线程处理脉冲期间应用,你有一个潜在的竞争条件,这可能导致损坏的共享状态,结果是不可预测的并且可能非常不受欢迎。

【讨论】:

  • 嗯,这可能是一个答案 - 竞争条件(特别是数据竞争)绝对不是 OP 似乎想要的“安全操作”,但现在信息太少了.究竟是什么导致了竞态条件?在这种情况下,究竟什么是不安全的(或更重要的是,不健全)?
  • 简短而有趣的解释。谢谢
猜你喜欢
  • 1970-01-01
  • 2013-11-25
  • 1970-01-01
  • 2012-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多