Use Platform.runLater
When not on the JavaFX thread, use Platform.runLater
to invoke a method which will ultimately update the GUI.
Doing this will schedule the code wrapped in runLater
to execute later on the JavaFX application thread.
As the JavaFX system is designed as a single-threaded system, this is necessary to allow the system to work consistently.
Higher level concurrency support in JavaFX
JavaFX also has higher level concurrency support using things such as Task
which have some communication support via methods such as updateMessage
. At an implementation level within Task, updateMessage
just uses Platform.runLater
internally, but includes some additional optimizations in its implementation to make it simple and efficient to use.
Usually, Tasks and Platform.runLater have different (sometimes complementary) focuses, see Javafx: Difference between javafx.concurent and Platform.runLater?.
In particular, for your requirement of UDP servers listening on multiple ports and feeding info back to a GUI, likely invoking runLater
directly is a more appropriate solution than using a JavaFX Task.
Answers to additional questions
However binding might work in my case
Do not use bindings, modify properties or trigger change listeners from another thread without wrapping the call in a Platform.runLater
call.
Binding and change listeners are not designed to work in a multi-threaded environment (for example if you concurrently modify the bindings or change listeners on different threads, the outcome may be unpredictable). Plus, if your binding or change listeners ultimately trigger changes to the active scene graph off of the JavaFX application thread, the outcome, again, may be unpredictable, as the scene graph is not designed to be used in that way.
At the moment I don't get how I should use the runLater() since I have no access to the relevant GUI elements from the thread class.
A few different options:
- Provide access to the GUI elements to the thread class, so it can modify them in a
runLater
call (this is a design modification for you) OR
- Have the thread class invoke a method on another class (via
runLater
) which does know about the GUI elements and can make the appropriate changes OR
- Use a shared model class with observable properties, which you have attached to a controller class that has established bindings or change listeners to update the UI based upon changes to the properties. From your thread you should read (see the link for a way to communicate from the GUI thread to another thread) and write the observable properties to the shared model class using
runLater
.
As you see, in all cases, eventually runLater
is used to schedule work which involves the GUI to be run later on the JavaFX thread, to enforce thread-safety within the system. And in all cases, if you don't have direct access to the GUI elements, you need to communicate with something that does so that it can make any necessary modifications on your behalf.