I have been doing some research on this but I am still VERY confused to say the least.
Can anyone give me a concrete example of when to use Task
and when to use Platform.runLater(Runnable);
? What exactly is the difference? Is there a golden rule to when to use any of these?
Also correct me if I'm wrong but aren't these two "Objects" a way of creating another thread inside the main thread in a GUI (used for updating the GUI)?
JavaFX contains the Platform class which has a runLater() method. The runLater() method takes a Runnable which is executed by the JavaFX application thread when it has time. From inside this Runnable you can modify the JavaFX scene graph.
Platform. runLater can be used to execute those updates on the JavaFX application thread.
It's generally recommended that you exit a JavaFX Application with a call to Platform. exit() , which allows for a graceful shutdown: for example if there is any "cleanup" code you need, you can put it in the stop() method and Platform. exit() will allow it to be executed.
exit() is called, or if the native process running the JVM is interrupted (e.g. ctrl-C on a *nix-like OS), in addition to the usual way of exiting a JavaFX Application. Note that it appears to be important to register the shutdown hook in the main thread, before calling Application. launch() .
Use Platform.runLater(...)
for quick and simple operations and Task
for complex and big operations .
Platform.runLater(...)
Task
: Task Example in Ensemble AppExample: Why Can't we use Platform.runLater(...)
for long calculations (Taken from below reference).
Problem: Background thread which just counts from 0 to 1 million and update progress bar in UI.
Code using Platform.runLater(...)
:
final ProgressBar bar = new ProgressBar();
new Thread(new Runnable() {
@Override public void run() {
for (int i = 1; i <= 1000000; i++) {
final int counter = i;
Platform.runLater(new Runnable() {
@Override public void run() {
bar.setProgress(counter / 1000000.0);
}
});
}
}).start();
This is a hideous hunk of code, a crime against nature (and programming in general). First, you’ll lose brain cells just looking at this double nesting of Runnables. Second, it is going to swamp the event queue with little Runnables — a million of them in fact. Clearly, we needed some API to make it easier to write background workers which then communicate back with the UI.
Code using Task :
Task task = new Task<Void>() {
@Override public Void call() {
static final int max = 1000000;
for (int i = 1; i <= max; i++) {
updateProgress(i, max);
}
return null;
}
};
ProgressBar bar = new ProgressBar();
bar.progressProperty().bind(task.progressProperty());
new Thread(task).start();
it suffers from none of the flaws exhibited in the previous code
Reference : Worker Threading in JavaFX 2.0
Platform.runLater
: If you need to update a GUI component from a non-GUI thread, you can use that to put your update in a queue and it will be handled by the GUI thread as soon as possible.Task
implements the Worker
interface which is used when you need to run a long task outside the GUI thread (to avoid freezing your application) but still need to interact with the GUI at some stage.If you are familiar with Swing, the former is equivalent to SwingUtilities.invokeLater
and the latter to the concept of SwingWorker
.
The javadoc of Task gives many examples which should clarify how they can be used. You can also refer to the tutorial on concurrency.
It can now be changed to lambda version
@Override
public void actionPerformed(ActionEvent e) {
Platform.runLater(() -> {
try {
//an event with a button maybe
System.out.println("button is clicked");
} catch (IOException | COSVisitorException ex) {
Exceptions.printStackTrace(ex);
}
});
}
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