I'm new with JavaFX and I've a little problem with a thread: I can execute it twice and I can't find why.
Here is a sum-upt of my code:
Task<Void> task = new Task<Void>() {
@Override public Void call() throws ImageLoadedException, HomographyException, IOException {
try{
System.out.println("GO !");
return null;
}
catch (Exception e){
e.printStackTrace();
}
return null;
}
@Override
protected void succeeded() {
super.succeeded();
System.out.println("SUCCEEDED");
}
};
@FXML protected void launch(ActionEvent event){
new Thread(task).start();
}
When I click a first time the button who start my thread, my task run without any problem (my console display "GO !" and "SUCCEEDED").
But if I click a second time, nothing append. Am I doing something wrong ? Can't we use a thread more than once ?
No. After starting a thread, it can never be started again. If you does so, an IllegalThreadStateException is thrown. In such case, thread will run once but for second time, it will throw exception.
JavaFX provides a complete package to deal with the issues of multithreading and concurrency. There is an interface called Worker, an abstract class called Task, and ScheduledService for this purpose. The Task is basically a Worker implementation, ideal for implementing long running computation.
The JavaFX scene graph, which represents the graphical user interface of a JavaFX application, is not thread-safe and can only be accessed and modified from the UI thread also known as the JavaFX Application thread.
Put inside the stop() method everything that needs to be executed before the JavaFX context terminates. With the System. exit(0) method, the application terminate abruptly.
From the Thread.start() documentation : No
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
From the Concurrency in JavaFX tutorial :
The Task class defines a one-time object that cannot be reused. If you need a reusable Worker object, use the Service class.
So, you have to consider the Service class rather than Task.
Edit: this should work for you:
Service service = new Service<>(task);
//Updated use this to create a new Service object instead
Service service = new Service() {
@Override
protected Task createTask() {
return new Task() {
@Override
protected Void call() throws Exception {
//Your codes here
return null;
}
};
}
};
@FXML protected void launch(ActionEvent event){
if (!service.isRunning()) {
service.reset();
service.start();
}
}
With a button can fire new tasks
Button btn = new Button();
btn.setText("New task");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Executor ex=new Executor("Task"+count);
ex.start();
count++;
System.out.println("Task Starting...");
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With