gpt4 book ai didi

java - 线程执行期间(/之后)数据的可见性

转载 作者:搜寻专家 更新时间:2023-11-01 02:46:06 25 4
gpt4 key购买 nike

在此示例中,有一个 Input 类和一个 Result 类的实例。输入实例填充在 GUI 线程中,这里是 JavaFX 应用程序线程。按下按钮后,此输入实例将在工作线程中使用。然后工作线程创建 Result 类的实例,并在调用此 Platform.runLater 更新 GUI 后用一些值填充它。

我的第一个问题是:是否保证工作线程看到 Input 实例的值?

我会说是的,原因如下:JLS 17.4.5。先于订单发生,说:在线程上调用 start() 发生在启动线程中的任何操作之前。

因此,从我的角度来看,在 JavaFX 线程之前开始时所做的一切都被调用将对工作线程可见。

我的第二个问题是:是否保证 JavaFX 应用程序线程看到 Result 实例的值?

我想是的,但我不确定。 Platform.runLater 会确保这一点吗?如何?

package javafxconcurrency;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class JavaFxConcurrency extends Application {

private Input input;

@Override
public void start(Stage primaryStage) {
input = new Input();
input.setId(1);
input.setName("Jack");

Button btn = new Button();
btn.setText("Start a thread");
btn.setOnAction(new EventHandler<ActionEvent>() {

@Override
public void handle(ActionEvent event) {
Task<Result> task = new Task() {

@Override
protected Object call() throws Exception {
final Result result = queryDB(input);
Platform.runLater(new Runnable() {

@Override
public void run() {
updateGUI(result);
}

});
return result;
}

private Result queryDB(Input input) {
try {
Thread.sleep(3000);
Result result = new Result();
result.setId(System.currentTimeMillis());
result.setName(input.getName());
return result;
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}

};
Thread workerThread = new Thread(task);
workerThread.setDaemon(true);
workerThread.start();
}

});

StackPane root = new StackPane();
root.getChildren().add(btn);

Scene scene = new Scene(root, 300, 250);

primaryStage.setTitle("Visibilty");
primaryStage.setScene(scene);
primaryStage.show();
}

private void updateGUI(Result result) {
System.out.println("result" + result);
}

public static void main(String[] args) {
launch(args);
}

private static class Input {

private long id;

private String name;

public void setId(long id) {
this.id = id;
}

public long getId() {
return id;
}

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

}

private static class Result {

private long id;

private String name;

public void setId(long id) {
this.id = id;
}

public long getId() {
return id;
}

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

@Override
public String toString() {
return "Result{" + "id=" + id + ", name=" + name + '}';
}

}

}

最佳答案

Is it guaranteed that the worker thread sees the values of the Input instance?

是的:Thread#start 创建了一个 happens before-relationship。所以你有:

  • input.setName("Jack"); happens-before workerThread.start(); 因为它们都在 FX 线程上所以你得到程序的保证订单
  • workerThread.start(); happens-before result.setName(input.getName()); 出于您提到的原因(线程启动之前的所有操作都发生在该线程中执行的任何操作之前)

Is it guaranteed that the JavaFX Application Thread sees the values of the Result instance?

是的,Platform.runLater 还提供了一个 happens-before 关系,如 the javadoc 所暗示的那样:“此方法 [...] 可以从任何线程调用”。如果你不相信你可以看看the code你会看到有几个同步点。

如果没有这种保证,就不可能在不手动同步所有内容的情况下与 JavaFX 组件进行通信。

关于java - 线程执行期间(/之后)数据的可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21708065/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com