In my program, I often make modifications to the UI using another thread.
The changes look like that:
buffer.add(new Object[]{message.getSecondNode().getUINode(), "red"});
Therefore I buffer these modifications in order to not overload the UI.
But in the following method the program does not make all the changes delivered in the buffer.
private void changeColor(List<Object[]> buffer) {
Platform.runLater(() -> {
for (Object[] object : buffer) {
if (object[0] instanceof UIEdge) {
UIEdge edge = (UIEdge) object[0];
edge.setColor((String) object[1]);
} else if (object[0] instanceof UINode) {
if ((String) object[1] == "red")
Util.print("");
UINode node = (UINode) object[0];
node.getEllipse().setFill(Paint.valueOf((String) object[1]));
}
}
});
}
In the following picture you see that the buffer has a different size in the method to its global size in the program.
Does anyone know why?
you might want to consider using JavaFX Service and Task instead of a buffer to make updates. These are JavaFX classes that are provided to make multi-threading easier in a JavaFX application.
https://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Task.html
Because the Task is designed for use with JavaFX GUI applications, it ensures that every change to its public properties, as well as change notifications for state, errors, and for event handlers, all occur on the main JavaFX application thread.
https://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Service.html
The Service by default uses a thread pool Executor with some unspecified default or maximum thread pool size. This is done so that naive code will not completely swamp the system by creating thousands of Threads.
Here's a brief tutorial if your not already familiar with them.
https://docs.oracle.com/javase/8/javafx/interoperability-tutorial/concurrency.htm
Related
I am making something similar to minecraft plugin, but the API is all in Java.
At some point, there are events. Every event is fired sequentially, and the API will wait until an event finishes before calling the event listener for the next event. These events are called from the main thread, this means that nothing else is running while your event listener code is being run, and the application will crash eventually if you are blocking the main thread for too long.
Basically, I want that when a player is opening an inventory, some first content is sent directly, and some second content is retrieved from a database. In Java, you, would do something like this:
private static final List<Item> firstContent = ...;
public static void onInventoryOpenEvent(Inventory inventory) {
inventory.addItems(firstContent);
forkJoinPool.submit(() -> { // "fire and forget"
List<Item> secondContent = retrieveContentFromDB(); // long and blocking
inventory.addItems(secondContent);
});
}
And in kotlin, some would say to use the GlobalScope, others would say to not use it, but for now I don't see any other way than using it like this:
fun onInventoryOpenEvent(inventory: Inventory) { // not a suspending function
inventory.addItems(firstContent)
GlobalScope.launch {
val secondContent = retrieveContentFromDB() // long and blocking
inventory.addItems(secondContent)
}
}
If you truly want to fire and forget, such that the coroutine will not be cancelled under any circumstance, GlobalScope is the right way to do it. The need to truly fire and forget is rare enough in practice that Kotlin gives you a warning about a "fragile API" if you use it, I think because so many newbies were using it for everything. This was especially a problem on Android (where Kotlin is primarily used), where long running tasks that should run even off-screen should be handled in services instead of coroutines.
But, referring to your example, if inventory is something that could become obsolete and you want to free it to the GC at some point, you should use your own created CoroutineScope that you store in a property, so you can cancel it to clear any running coroutines and prevent them from hanging onto references that should be freed for the GC. If the scope might be used for more than one coroutine, then you should give it a SupervisorJob().
private val coroutineScope = CoroutineScope(SupervisorJob())
fun onEndOfLifecycle() { // some function called when cleaning up memory
coroutineScope.cancel()
}
When I need to do an indeterminate number of pieces of work in the JavaFX thread without blocking the user interface, I use this class
public class AsyncWhile {
private final IntPredicate hook;
private int schedCount = 0;
private boolean terminated = false;
private int callCount = 0;
private static final int schedN = 1;
public AsyncWhile(IntPredicate hook) {
this.hook = hook;
schedule();
}
public void kill(){
terminated = true;
}
private void schedule(){
while(schedCount < schedN){
Platform.runLater(this::poll);
schedCount++;
}
}
private void poll(){
schedCount--;
if(!terminated){
terminated = !hook.test(callCount++);
if(!terminated){
schedule();
}
}
}
}
like this
asyncWhile = new AsyncWhile(i -> {
// return false when you're done
// or true if you want to be called again
});
// can asyncWhile.kill() should we need to
(
If you need a more concrete example, here I'm reading one line at a time from an InputStream and then parsing and displaying a plot parsed from that line:
asyncWhile = new AsyncWhile(i -> {
String line;
try {
if((line = reader.readLine()).startsWith(" Search complete.")){ // it so happens that this reader must be read in the JavaFX thread, because it automatically updates a console window
return false;
} else {
Task<MatchPlot> task = new ParsePlotTask(line);
task.setOnSucceeded(wse -> {
plotConsumer.accept(task.getValue());
// todo update progress bar
});
executorService.submit(task);
return true;
}
} catch (IOException ex) {
new ExceptionDialog(ex).showAndWait();
return false;
}
});
)
Chaining up runLaters like that feels like a hack. What is the proper way to solve this kind of problem? (By "this kind of problem" I mean the problem that would have been solved by a simple while loop, had it not been for the fact that its contents must run in the JavaFX thread without making the UI unresponsive.)
Recommended
In general, basing a solution off of the PartialResultsTask sample from the Task documentation (which relies on Platform.runLater invocations), is the standard way of solving this problem.
Alternate
Rather than scheduling runLater's you could use a BlockingDeque. In your processing task, you perform your time-consuming process just with a normal while loop, generate non-UI model objects which need to be represented in the JavaFX UI, stick those non-UI model objects into your queue. Then you setup a Timeline or AnimationTimer that polls the queue, draining it as necessary and to pick the items off the queue and represent them in the UI.
This approach is similar (but a bit different) to: Most efficient way to log messages to JavaFX TextArea via threads with simple custom logging frameworks.
Using your own queue in this case is not much different from using the implicit queue runLater invocations go on to, though, with your own queue, you might have a little more control over the process if you need that. It's a trade-off though, as it adds a bit more custom code and complexity, so probably just use the recommended PartialResults sample from Task and, if that doesn't fit your needs, then perhaps investigate the alternative custom queue based approach.
Aside
As a side note, you could use the custom logging framework linked earlier to log console messages from multiple threads to be displayed in your UI. That way you don't need to have your reader.readLine call execute I/O on the JavaFX UI, which is not recommended. Instead, have the I/O performed off the JavaFX UI thread and, as you process items, call into the logging framework to log messages that will eventually show up on the UI (the internal mechanisms within the logging framework take care of ensuring that JavaFX threading rules are respected).
Can you see any danger in using my approach?
Sorry for being non-specific here. I'm not going to directly answer this, but tangentially and not always applicably to your approach, using runLater can cause issues, mostly it is not a concern, but some things to consider:
If you send enough runLater calls faster than they can be processed, eventually you will either run out of memory or some runLater calls will start being ignored (depending on how the runLater system works).
Calls to runLater are sequential, not prioritized, so if there are internal events which are also being runLater, such as handling UI events, those might be delayed while your runLater calls are being processed.
runLater offers no guarantee of when later is. If your work is time sensitive, that might be an issue or at least something you need to account for in your implementation.
The runLater system is likely internally fairly complex and you won't know exactly how it is implemented unless you study the source code pretty closely.
Anything that you run on runLater is going to hold up the JavaFX application thread, probably until all of the outstanding runLater calls are complete
Once you have issued a bunch of runLater calls, you can't easily intersperse their processing over multiple pulses in the JavaFX animation system, they will likely all be executed on the next pulse. So you have to be careful not to send too many calls at once.
Those are just some things that come to mind.
In general though, runLater is a sound mechanism for many tasks and a core part of the JavaFX architecture. For most things the above considerations don't really have any consequence.
Writing quality multi-threaded code is pretty tricky. To the point where it often best avoided where possible, which is what the JavaFX system attempts to do for the most part by making scene graph access single-threaded. If you must do it, then stick to the patterns outlined in the Task documentation or utilizing some of the high level java.util.concurrent systems as much as possible rather than implementing your own systems. Also note that reading multi-threaded code is even trickier than writing it, so make sure what you do is clear to the next person.
I must say that I'm new to Java and JavaFX (less than 2 months), and also my UML skills are not perfect, so I might have used wrong blocks or/and connectors on the diagram :) But I hope you get an idea.
I have an order management app with a following (simplified to essentials) design:
OMS app design
Put very simply, the JavaFX GUI displays in a table view what is happening (i.e. the current state of the orders) between the client (that sends orders) and the broker (on the other end of the network connection). Order Manager is the only entity that has access to modify the model (i.e., the list of orders and their fields), and all methods modifying the model are synchronised (so it's safe to call them from any thread).
The orders are JavaFX beans, with different fields implemented as JavaFX Properties. These properties are bound to table columns in the GUI, so whenever the Order Manager updates a field, the change is propagated to the GUI via the binding mechanism.
Now, because the property binding mechanism is not thread-safe (see the following rule:
An application must attach nodes to a Scene, and modify nodes that are already attached to a Scene, on the JavaFX Application Thread.
), I have to wrap all the code modifying those fields, in Platform.runLater() calls, for example:
public void onOrderCanceled(int id, String reason) {
Order order = orderbook.get(id);
if(order == null) {
throw new IllegalArgumentException("Order "+id+ " not found");
}
Platform.runLater(() -> {
order.setReason(reason);
order.setStated(CANCELED);
subscribers.foreach(sub -> sub.notifyUpdated(order));
});
}
This approach has the following unpleasant implications:
The client notification is delayed by an arbitrary time (till the GUI thread finishes processing its message queue). Reason: I cannot notify the client before the order fields are updated (or it will have incorrect data), and I can only update the fields in the GUI thread.
Because the state of the order is not modified right away but at some future point, there exists for some time an incoherence between the order object and the actual order state.
If the GUI thread gets blocked or becomes very slow (because of bugs or design flaws), the client code is blocked or slowed down (while waiting for the notification that is stuck in the GUI thread's message queue).
Is there a better way of doing that? Ideally, I would like a solution that:
Allows the client code to communicate with the networking layer (via the order manager) as fast as possible, i.e. without waiting for the GUI to catch-up
The GUI is allowed to lag behind a little bit, but must not "skip" field updates, or at least never drop the most recent update (which is the most relevant)
Rely on the FX property binding architecture to update the GUI (which I find very convenient)
I feel that I need to create another "model" for the GUI that will be updated in the FX thread only, while the "real" model will be used by the order manager and the client code, and I need to ensure to maintain the two models in sync (which is creepy).
Was FX designed without multithreading in mind? I had a look on the Task and Service interfaces, but is doesn't look like something appropriate (in my case, GUI doesn't initiates a task - it comes from an external source, the client code or the network).
Thanks in advance!
If I understand this implementation correctly, you are performing the notification to remote clients on the FX Application Thread. You're doing this because you need to send the clients the updated version of the Order object, and since this object is bound to the table, changes to its state can only happen on that thread.
This is somewhat perilous, as those remote notifications may take time, and so you may block the UI thread, causing a lack of responsiveness. Additionally, you are forcing the logic of the application to wait for the (potentially blocked) UI thread. This is the opposite way around to the way you should be doing things: your application logic should flow in a thread of execution in a natural way, and you should arrange for the FX Application Thread to show the latest version of the data in as lightweight a way as possible on each frame rendering.
I think what you need here is a separate, immutable class to represent the updates. You'll send those to your clients, and then on successful notification update the UI, instead of driving the application from the UI. So something like
public abstract class Update {
private final int orderId ;
public Update(int orderId) {
this.orderId = orderId ;
}
public abstract void performUpdate(Order order) ;
public int getOrderId() {
return orderId ;
}
}
and
public class Cancelation extends Update {
private final String reason ;
public Cancelation(int orderId, String reason) {
super(orderId);
this.reason = reason ;
}
public String getReason() {
return reason ;
}
#Override
public void performUpdate(Order order) {
if (order.getId() != getOrderId()) {
throw new IllegalArgumentException("Wrong order");
}
order.setReason(reason);
order.setState(CANCELED);
}
}
Now in your application code you can do something like
public void onOrderCanceled(int id, String reason) {
Order order = orderbook.get(id);
if(order == null) {
throw new IllegalArgumentException("Order "+id+ " not found");
}
Task<Update> updateTask = new Task<Update>() {
#Override
public Update call() throws Exception {
Update update = new Cancelation(id, reason);
subscribers.forEach(sub -> sub.notifyUpdate(update));
return update ;
}
};
updateTask.setOnSucceeded(e -> updateTask.getValue().performUpdate(order));
updateTask.setOnFailed(e -> {
Exception exc = updateTask.getException();
// handle exception
});
subscriberNotification.execute(updateTask);
}
Now you schedule updates in an executor dedicated to that particular functionality, and then update the UI when you know the notification has happened. In other words, the UI responds to the application logic, instead of the other way around. Your clients now receive the details of the update, and presumably they have their own representation of the Order (perhaps instances of the same class), and can update their own representations using the information in the Update. Note this will likely save you network traffic too (probably the biggest bottleneck in your application), because you only communicate the changes, instead of the entire object. Of course, this might entail some major refactoring of your code (sorry about that...).
It's going to be important that the updates are all transmitted in the correct order, so you should use a single thread of execution for managing them. In other words, you need something like
private final Executor subscriberNotification = Executors.newSingleThreadedExecutor();
I'm modeling a prototype that will use JavaFX.
The application will be similar with a kiosk, for self service. however before the client interact with it, the administrator should unlock it. The administrator will be able to send some remote commands, via a dedicated channel (HTTP or IPC or USB device). Examples of command would be: start, stop and reset
How should I do it?
a) Can I have a Task, running in another thread pooling actively an IPC and if there is message there, switch the Scene?
b) to have a reactor running in a thread and as soon receives a command, it pass it to the JavaFX thread.
are both options valid? does exist a third one?
Both your options (a) thread with Task and (b) thread without task are valid.
Recommended Solution
I'd choose option b (thread without a task).
The key part of the solution is the line:
Platform.runLater(() -> MyApplication.changeScene(newData));
Task is good, but probably not best for your situation
Task is good if you have something which is initiated by the UI or JavaFX thread. For example, the user clicks a button and you want to retrieve data from a server based upon that action, feeding back progress reports via messages and progress bar updates as the data is retrieved. So Task is very good for that kind of operation because it has explicit support for things such as the message feedback and progress updates as well as a well defined state model for when the task starts and completes. See invariants code example to understand how Task improves such situations: Platform.runLater and Task in JavaFX.
However, when the initiator of the event is off the JavaFX application thread, there isn't much advantage in using a Task versus just using traditional concurrency utilities. This is because you typically don't need the extra services that the Task is providing such as the progress and message update APIs and its state machine. Also, libraries that are initiating such events typically already have their own thread model setup, so you don't need the extra threading framework provided by a Task.
Using Platform.runLater()
All you really want is a notification that something happened. Now that notification needs to occur on the JavaFX application thread as you can't manipulate items in an active scene using another thread. To get an event passed to the JavaFX application thread, you use the Platform.runLater(runnable) construct.
Sample Code
I won't write Ruby, because I really can't, but here is some code in Java to give you the gist - it's actually really simple.
class DataReader implements Runnable {
private final DataSource dataSource;
public DataReader(String location) {
dataSource = new DataSource(location);
Thread thread = new Thread(this);
thread.setDaemon(false);
thread.start();
}
public void run() {
while (dataSource.hasData()) {
MyImmutableObject newData = dataSource.getSomeData();
Platform.runLater(() -> MyApplication.changeScene(newData));
}
}
}
class MyApplication extends Application {
public void changeScene(MyImmutableObject newData) {
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"layout.fxml"
)
);
UIController controller =
loader.<UIController>getController();
controller.initData(newData);
Scene scene = new Scene((Pane) loader.load());
stage.setScene(newScene);
}
}
The above sample makes use of fictional DataSource, MyImmutableObject and UIController classes and a fictional FXML template to demonstrate the concept (so the snippet is not a standalone runnable thing). The FXML loading concepts come from: Passing Parameters JavaFX FXML. The sample code creates its own thread, but if whatever you library you are using already creates threads itself (which is likely), you don't need to create another one, you can just add appropriate hooks into the existing library with Platform.runLater calls to get the event notification and passing of data between the library threads and your JavaFX application.
Related Questions
There are numerous other questions on Platform.runLater versus Task on StackOverflow:
Javafx: Difference between javafx.concurent and Platform.runLater?
JavaFX 2: background and Platform.runLater vs Task/Service
Additional Questions
in my case, the administrator will be able, in some cases, to send an initial information to the kiosk, almost like an (initialization vector), for example the passport number. With this information, still the Platform.runLater the best solution?
Yes, Platform.runLater is still the best solution. You will have some thread which is alerted when the administrator sends the information to the kiosk (e.g. a servlet on an embedded http server or a jax-rs service) and it can invoke Platform.runLater to update the JavaFX based kiosk UI based on that info.
I am looking for a way to do what the InvokeLater() function does only instead of putting the event on the bottom of the event queue it puts it on top. At least I think that will do what I want, maybe there's a better way. Below describes what I'm trying to replicate.
Years ago I use a c++ framework on the Mac that had feature that you could add a Chore object to a CriticalChore list while processing the current event. You would do this while executing code in what amounts to Swings EDT. After the current event was finished being processed and just before calling GetNextEvent() the Framework would check if the CriticalChore list was empty. If the list had items in it there Perform() (i.e. run()) function would be called. When finished with the list all the items were then deleted.
This feature came in really handy. Many times while handling an event early on you know you need to perform some additional code but only after a lot of other code is processed. But most importantly, is this code needs to be processed before any other events from the EDT queue are handled.
I don't see any method of doing that. I suppose that you could do some hacky stuff to make your own method of injecting higher priority actions.
I think the best answer, though, is to not do this at all. If you have a need to do so, the design probably needs to be reworked. The EventDispatchThread is supposed to be only for very short-running actions as it's never supposed to look to the end user as though the application has frozen. Because of this, the queue for the EDT should always be short enough that anything you put on it will happen "instantly" from the point of view of the user, so everything on it should have "instant" priority.
If anything needs to be done which is not a very short-lived action, there is a separate methodology for doing that. There is a Swing Worker class for that, and you are supposed to use this to set up tasks that run alongside the EDT and listen for its responses.
Here is a Swing Worker Tutorial. There are also some other good ones that Google pulls up with a "Java SwingWorker tutorial" query.
First, how's done
It's possible to install a global listener with its own queue and one each event polling the queue. Toolkit.addAWTEventListener(listener, eventMask)
There is a sun.awt.PeerEvent (for sun impl) that has an ultimate priority which offers the easiest impl since it's practically the same as EventQueue.invokeLater extending java.awt.event.InvocationEvent but again it's not standard.
Last:
Here how is done standard way, I have not tested the code, though (lazy & very late)
class EventQueueX extends EventQueue{
final ConcurrentLinkedQueue<AWTEvent> que=new ConcurrentLinkedQueue<AWTEvent>();
#Override
public AWTEvent getNextEvent() throws InterruptedException {
AWTEvent e = que.poll();
if (e!=null)
return e;
return super.getNextEvent();
}
#Override
public synchronized AWTEvent peekEvent() {
AWTEvent e = que.peek();
if (e!=null)
return e;
return super.peekEvent();
}
public void pushFirst(AWTEvent e){
que.offer(e);
synchronized (this) {
notify();
}
}
public void install(Toolkit toolkit){
EventQueue q = toolkit.getSystemEventQueue();
if (q!=this)
q.push(this);
}
};
Use the EventQueueX.install() and then pushFirst(e) when you want an event and you're set. Unfortunately the queue will get deinstalled on an exception and might be pushed away too.
Next, why is bad
To the question. putting an event in the front of the queue is a bad idea overall.
If you have to call any code later on just structure your own design and at the end of the function invoke the necessary code, use a Queue if you need be.
Adding an extra layer of super ultimate priority might look ok, but it's a hard to understand design concept for any regular AWT/Swing (UI mostly) developer. If you need to queue actions, use your own mini-framework w/o messing up with awt. While I am particularly good at hacking, even I, myself, would fine such an approach weird (to put it mildly).