从Platform.runLater线程运行的代码安全吗?

时间:2019-09-08 15:41:44

标签: javafx

如果我的代码完全是在Platform.runLater内部运行的,那么代码是否自动线程安全?

我的理解是,在Platform.runLater上运行的代码在JavaFX应用程序线程上运行,该线程只有一个。

例如,如果我完全在Plaform.runLater中操作哈希映射,则不必担心多个线程,对吗?

1 个答案:

答案 0 :(得分:3)

是否使用Platform#runLater(Runnable)是线程安全的,这完全取决于您的使用方式。您给出的示例是您有一个Map从后台线程可见,但是只能通过runLater JavaFX Application Thread 上对其进行操作。也许像这样:

// executing on background thread
Object newKey = ...;
Object newVal = ...;
Platform.runLater(() -> map.put(newKey, newVal));

仅从 JavaFX Application Thread 的角度来看,这使Map是“线程安全的”。如果后台线程稍后尝试读取Map(例如map.get(newKey)),则不能保证该线程将看到新条目。换句话说,它可能会读取null,因为条目“不存在”,或者它可能会读取旧值(如果已经存在)。您当然也可以通过阅读 JavaFX Application Thread 来解决此问题:

Object val = CompletableFuture.supplyAsync(() -> map.get(key), Platform::runLater).join();

或者甚至通过等待 JavaFX Application Thread 完成对Map的写入:

CountDownLatch latch = new CountDownLatch(1);
Platform.runLater(() -> {
    // write to map
    latch.countDown();
});
latch.await();
// writes to map will be visible to background thread from here

也就是说, JavaFX应用程序线程将看到在调用runLater之前发生的后台线程的操作。换句话说,创建了一个先于关系。在安排Runnable JavaFX Application Thread 上执行时,最终必须发生一些线程间通信,这又需要同步才能保证线程安全。在JavaFX的Windows实现上,我无法确定这种同步是什么样的,因为它似乎调用了本机方法。