Home > front end >  Hello, I have a multithreading program , each thread has to store a value in a ThreadLocal variable,
Hello, I have a multithreading program , each thread has to store a value in a ThreadLocal variable,

Time:01-30

I'm trying to write this multithread program , but somethings goes wrong. I have an HelloApplication class , I create two new thread there.

The run method is in another Class named ThreadLocalSession. There I need to store two different value , one for each thread using a ThreadLocal Variable. This way failed because the second thread overwrite the value written by the first one.

For this reason I tried to print the thread id and I noticed that the same Thread Id and thread name is printed two time ... How is it possible ?

This is the HelloApplication class :

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

This is the ThreadLocal session Class:

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;

}
}

Then I want to print the value of the two value stored by the thread and display them where a button is pressed. This is it's graphic controller :

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

}

Finally this is the Session:

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

}

I don't know why the ''' ThreadLocal userSession''' is overwrited , and why the same thread id is printed two different time in the run despite of i have lunched two different thread.

CodePudding user response:

This is because Platform.runLater runs the provided Runnable on the JavaFX Application Thread, not the thread that calls it.

Dealing with multiple threads in a GUI application can be a little more complicated, because the GUI itself is usually single-threaded and unsafe to access from other threads. You can read a basic introduction to the concepts in this article: "Multithreading in JavaFX".

Because of this, it can be hard to reason about how thread local variables propagate in the application. It would be preferable to explicitly pass context as method parameters.

CodePudding user response:

Executing display is Platform.runLater, not new Thread().I haven't used Platform.runLater, but I think it's a thread pool.

  •  Tags:  
  • Related