你好,我有一个多线程程序,每个线程都必须在 ThreadLocal 变量中存储一个值,但是第二个线程覆盖了 1 的内容

Lor*_*tti -3 java multithreading javafx

我正在尝试编写这个多线程程序,但出了问题。我有一个 HelloApplication 类,我在那里创建了两个新线程。

run 方法位于另一个名为 ThreadLocalSession 的类中。在那里,我需要存储两个不同的值,每个线程使用 ThreadLocal 变量存储一个值。这种方法失败了,因为第二个线程覆盖了第一个线程写入的值。

由于这个原因,我尝试打印线程 id,我注意到相同的线程 ID 和线程名称被打印了两次......这怎么可能?

这是 HelloApplication 类:

public class HelloApplication extends Application {

@Override
public void start(Stage stage) throws IOException {
    ThreadLocalSession firstUser = new ThreadLocalSession(1);
    ThreadLocalSession secondUser = new ThreadLocalSession(2);
    new Thread(firstUser).start();
    new Thread(secondUser).start();
}

public static void main(String[] args) {
    launch();
}
}
Run Code Online (Sandbox Code Playgroud)

这是 ThreadLocal 会话类:

public class ThreadLocalSession implements Runnable{

private static final ThreadLocal<Session> usersession= new ThreadLocal<Session>();
private Integer tr_id;

public ThreadLocalSession(int i) {
    this.tr_id =i;
}


@Override
public void run() {
    Platform.runLater(() -> {
        try {
            display();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });

   }

 public static ThreadLocal<Session> getUsersession() {
    return usersession;
 }

 private Runnable display() throws IOException, InterruptedException {
    System.out.println(Thread.currentThread().getId());
    System.out.println(Thread.currentThread().getName());
    Scanner scanner = new Scanner(System.in);
    System.out.println("inserisca messaggio : ");
    String str = scanner.nextLine();
    Session session = new Session(str);

    usersession.set(session);
    System.out.println(usersession.get().getNamee());


    Stage stage = new Stage();
    FXMLLoader fxmlLoader = new  
    FXMLLoader(ThreadLocalSession.class.getResource("hello-view.fxml"));

    Scene scene = new Scene(fxmlLoader.load());
    stage.setTitle("Mate");
    stage.setScene(scene);
    stage.showAndWait();
    return null;

}
}
Run Code Online (Sandbox Code Playgroud)

然后我想打印线程存储的两个值的值并在按下按钮的位置显示它们。这是它的图形控制器:

public class HelloController {
@FXML
private Label welcomeText;

@FXML
protected void onHelloButtonClick() {
   // System.out.println(userSession.get().);
    Session se = ThreadLocalSession.getUsersession().get();
    welcomeText.setText("Welcome to JavaFX Application!"+ se.getNamee() +"by");
}
Run Code Online (Sandbox Code Playgroud)

}

最后这是会议:

public class Session {
    private String name;

    public Session (String name ){
        this.name = name ;
    }

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

    public String getNamee() {
        return name;
    }

}
Run Code Online (Sandbox Code Playgroud)

我不知道为什么 ''' ThreadLocal userSession''' 被覆盖,以及为什么相同的线程 id 在运行中两次不同的时间打印,尽管我已经午餐了两个不同的线程。

Tim*_*ore 5

这是因为在 JavaFX 应用程序线程上Platform.runLater运行提供的Runnable,而不是在调用它的线程上运行。

在 GUI 应用程序中处理多个线程可能会稍微复杂一些,因为 GUI 本身通常是单线程的,并且从其他线程访问是不安全的。您可以阅读本文中概念的基本介绍:“JavaFX 中的多线程”

因此,很难推断线程局部变量如何在应用程序中传播。最好将上下文作为方法参数显式传递。