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



我正试图编写这个多线程程序,但出现了一些问题。我有一个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();
}
}

这是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;
}
}

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

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");
}

}

最后是会议:

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;
}
}

我不知道为什么"ThreadLocal userSession"被覆盖,也不知道为什么同一个线程id在运行的两个不同时间被打印出来,尽管我吃了两个不同的线程。

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

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

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

执行displayPlatform.runLater,而不是new Thread()。我没有使用Platform.runLater,但我认为它是一个线程池。

最新更新