JavaFX Multithreading

1.8k Views Asked by At

I am facing one problem in my JavaFx application.

Preface: I don't want to be specific to my application only but want to be generalized so that people like me will get an idea on similar situation.

Background: Implementing a Javafx application using fxml file and multi-threading concept.

Summary: I tried make an application which basically uses multi threading to do some task, and once multi- threading is completed, it will sequentially move to another task. While doing the multi-threading the Main GUI freezes.

What I did,

//This is Main class

Parent Root  -> defined on top
public Parent createContent(){
 try{
  root =  FXMLLoader.load(getClass().getResource("Layout.fxml"));
  }catch { .....}
 }

 public void start(){
    stage.setScene(new Scene(createContent()));
    Task<Void> task = new Task<Void>() {
            @Override
            public Void call() throws Exception {
                Thread.sleep(1000);
                return null ;
            }
        };
      task.setOnSucceeded(event->{
            stage.show();
        });
        new Thread(task).run();
  }
  public static void main(String[] args) {
        launch(args);
    }
// This is inside the controller on button click event
@FXML
private void start(ActionEvent event) { <---- This one is button click event
   Thread t1 = new Thread(new Mul());
    t1.start();
    Thread t2 = new Thread (new Mul());
    t2.start();
}

 // Finally 
public class Mul implements Runnable {
  public void type() {
    for (int a = 0; a < 200000; a++) {
        System.out.println( Thread.currentThread().getName()+ " says " + a);
    }
   }
    @Override
   public void run() {
     type();
   }

}

Now, here is the outcome. If I just start the threads from the controller then My main application does not freezes while the thread are running in background. However, since the application runs in a sequence, i.e the next step only works when the threads complete their work

I can use t1.join() and t2.join() , but doing so will freezes my main application(Main application here is the main GUI) and I cannot proceed with it until the threads are completed.

What could be the optimal solution, so that I can use multi threading without blocking the main application or What am I doing wrong here? (info, I came to this solution by following up different suggestions from Stack overflow and google)

1

There are 1 best solutions below

0
On BEST ANSWER

Why not do

Task<Void> task = new Task<Void>() {
    @Override
    public Void call() {
        Mul m1 = new Mul();
        m1.run();
        Mul m2 = new Mul();
        m2.run();
        return null ;
    }
};
new Thread(task).start();

If you really want to "chain" different tasks, call one from the other's onSucceeded handler:

Task<Void> task1 = new Task<Void>() {
    @Override
    public Void call() {
        new Mul().run();
        return null ;
    }
};

Task <Void> task2 = new Task<Void>() {
    @Override
    public Void call() {
        new Mul().run();
        return null ;
    }
};

task1.setOnSucceeded(e -> new Thread(task2).start());

new Thread(task1).start();

Obviously this is cleaner if you make Mul a Task subclass instead of a Runnable, and it's better to use an Executor with daemon threads, etc, but this should give you the idea.