【发布时间】:2015-12-06 12:42:54
【问题描述】:
我通过修改可观察数组列表来更新表,但现在 2 个线程可能会修改可观察数组列表。我应该将修改列表的代码放在同步方法中,还是只允许 1 个线程修改列表?
【问题讨论】:
-
如果修改您的
ObservableList会更改您的TableView,那么您只能从 FX 应用线程访问它。
标签: java multithreading javafx thread-safety
我通过修改可观察数组列表来更新表,但现在 2 个线程可能会修改可观察数组列表。我应该将修改列表的代码放在同步方法中,还是只允许 1 个线程修改列表?
【问题讨论】:
ObservableList 会更改您的TableView,那么您只能从 FX 应用线程访问它。
标签: java multithreading javafx thread-safety
不,ObservableList 的实现只是一个包装器,它在普通 List(普通 java 集合)上添加了 listner 方法
所以它不是线程安全的,你可以去看看ObservableListWrapper的源码。
更多信息:https://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm
【讨论】:
您可以通过调用从 ObservableList 创建同步的 ObservableList
javafx.collectionsFXCollections.synchronizedObservableList(observableList)
这将为您的 observableList 创建一个包装器,您可以使用它来将项目添加到您的列表中。
问题是同步对您意味着什么。因为技术同步并不一定意味着它在您的业务需求方面是同步的,例如如果您必须通过在列表中按顺序调用 add(...) 两次来添加 2 个项目,并确保它们按顺序包含(中间没有其他项目)。也许您无论如何都必须确保在不同级别上进行同步。
【讨论】:
ObservableList 绑定到TableView,那么您必须只能从单个线程(FX 应用程序线程)访问它。当您只能从一个线程访问它时,使用同步列表或添加您自己的同步将毫无意义。
ObservableList 可以通过创建 Runnable r 调用 javafx.application.Platform.runLater(r) 来实现。
Platform.runLater 中说明了这一点。
对于这个特定的用例——ObservableList 绑定到TableView,您只能从 FX 应用程序线程访问该列表。这是因为对列表的更改会导致TableView 和all changes to the scene graph must occur on the FX Application Thread 的更改。
所以在这种情况下,ObservableList 是否是线程安全的问题是一个有争议的问题:由于其他原因您只能从单个线程访问它,因此您不需要它。
如果您有一个需要更新列表的后台线程,您可以将这些更新安排在 FX 应用程序线程上,方法是将它们包装在对 Platform.runLater(...) 的调用中,或者(这可能更可取)使用javafx.concurrent API 来管理你的线程。
【讨论】:
onSucceeded 处理程序可以简化为 event -> jobData.addAll(tableLoader.getValue()) 但是是的,这看起来是正确的。