【问题标题】:How to deal with JavaFX's threading model and large data changesJavaFX的线程模型和大数据变化如何处理
【发布时间】:2019-06-28 23:36:14
【问题描述】:

我有一个ObservableList 的“曲目”显示在TableView 上。 ObservableList 的内容基于从磁盘读取的元数据。

有时我必须从ObservableList 中添加或删除大量数据。某些列表修改可能需要 5 秒或更长时间(例如,通过从 50000 个列表中删除 5000 个特定曲目)。

JavaFX 规定对支持TableViewObservableList 的任何更改只能在JavaFX 线程上完成。如果我在 JavaFX 线程上执行 5 秒事务,程序 UI 将冻结 5 秒,这是不可接受的行为。

我目前的解决方案是将我对主列表的更改分解为除了修改列表之外什么都不做的小事务。我将这些更改放入一个队列中,然后在 JavaFX 线程的每个循环中仅在几百毫秒内处理来自该队列的任务,以避免导致 UI 卡顿。

这很好用,但会产生其他问题,我无法管理或封装,这让我怀疑这不是一个很好的解决方案。

例如,检查 Track 是否在 ObservableList 中现在是一个复杂的过程,我必须检查 ObservableList、待处理的操作队列,然后找出列表的最终状态是什么将在处理所有操作时,并基于此返回。这既麻烦又容易出错。此模型还会在迭代由多个线程共享的列表时产生问题。

我正在寻找更好的解决方案来解决这个问题,因为列表 + 挂起的更改队列方法笨重且容易出错。

问题归结为:管理必须在 JavaFX TableView 上显示的大量对象的更改的最佳结构是什么?

【问题讨论】:

  • 如果这是 Java Swing,我会说使用 SwingWorker. 它为您管理后台任务。我不知道如何将其翻译成 JFX(假设需要任何翻译)。
  • @markspace 等效于 SwingWorker 的是 TaskService(它们都恰好继承了 Worker 接口)。
  • 您只是在更改列表中的哪些元素?或者你可能会修改元素本身?
  • JavaFX 的Task / Service(如@VGR 所述)和RxJavaFX 都可以帮助将列表管理工作移出JavaFX GUI 主线程。
  • 确实可以在另一个线程中准备一个新列表,然后在事件线程中更新当前列表。

标签: java multithreading javafx


【解决方案1】:

似乎运行良好的解决方案是这样的:

  1. 创建一个名为 items 的 ObservableList,它是规范数据集。
  2. 工作线程可以随意修改items
  3. items 添加更改侦听器。将更改推送到项目时,记下更改内容并将其放入名为pendingChanges 的队列中。
  4. 创建名为displayCache 的第二个ObservableList,它是JavaFX 中显示的数据集。
  5. 每隔一段时间,让 JavaFX 线程从pendingChanges 拉取更改并将它们应用到displayCache

通过这种方式,我们拥有了一个实时准确的数据集,并且 JavaFX UI 中显示的项目正试图赶上该数据集。如果 UI 落后几秒钟,那根本不重要。

我昨晚实现了这个,连同一些代码来适当地管理阻塞和锁定,它基本上马上就工作得很好。我能够将所有这些封装到一个类中,这意味着我的其余代码不必考虑管理缓存、管理线程问题或类似的事情。

这与之前的解决方案相反。我一直在制作 displayCache 规范数据集,这带来了许多其他问题。通过拥有一个可以实时更新的独立的非 JavaFXThread 数据集,我能够回避所有这些问题并将延迟放在它所属的地方——在数据集和 UI 之间。

【讨论】:

    猜你喜欢
    • 2018-04-05
    • 1970-01-01
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-27
    • 2013-07-02
    相关资源
    最近更新 更多