"Asynchronous while loop" in JavaFX thread - java

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.

Related

Platform.runLater() with Lambda Expression not working

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

Assertions or Annotations for thread correctness

I am coding as part of a project which uses multithreading and I'm trying to find ways to detect thread mistakes in my code.
Are there some existing tools I could use to help me do this?
For example-
an assert that my method is being called by the correct thread
or
some kind of static checking with annotations, similar to #Nullable and #NotNull, to detect when my code calls a method from the wrong thread.
Although the project is multithreaded, there is almost no synchronisation required because the different threads don't access the same objects, they have their own instances.
Broadly speaking, there are four threads running at once
Server thread = maintains the state of the game for one or more
clients
Client thread = processes user input, maintains a local
copy/cache of server data for rendering
NetworkMessage thread = processes incoming/outgoing messages
between server and client
Render thread = processes the local data into rendering information for the
graphics card
The classes are sometimes intended for only one of the threads (for example user input polling is client-only), sometimes they are for multiple threads (eg the calculated movement of a projectile uses the same code on both client and server simultaneously to reduce perceived lag). Several times I've called a method from the wrong thread, leading to subtle and unrepeatable bugs and very nearly serious monitor screen damage (from my fist)
What I have thought of so far is something like this:
public void myMethodThatAssumesClientThreadOnly() {
assert checkThread(CLIENT);
// can now happily call other client-thread code without fear
}
but I would prefer something with static checking similar to #Nullable
eg
#Thread(CLIENT)
void myClientMethod() {
//client-only stuff here
}
#Thread(SERVER)
void myServerMethod() {
//server-only stuff here
}
#Thread(CLIENT + SERVER)
void myClientAndMethod() {
myClientMethod(); // error- server thread might call client method
}
Unfortunately, being an annotation noob, I have no clue whether this is easy or actually very hard.
Any pointers? I can't imagine I'm the first one to look for something like this.
TGG
The Checker Framework enables the creation of compile-time static checkers that verify program correctness. Its GUI Effect Checker is similar to what you want. Here is an abridged excerpt from its manual:
One of the most prevalent GUI-related bugs is invalid UI update or invalid thread access: accessing the UI directly from a background thread.
If a background thread accesses a UI element such as a JPanel (by calling a JPanel method or reading/writing a field of JPanel), the GUI framework raises an exception that terminates the program.
It is difficult for a programmer to remember which methods may be called on which thread(s). The GUI Effect Checker solves this problem. The programmer annotates each method to indicate whether:
It accesses no UI elements (and may run on any thread).
It may access UI elements (and must run on the UI thread).
The GUI Effect Checker statically enforces that UI methods are only called from the correct thread.
The GUI Effect Checker is tuned to detect and prevent GUI threading errors, whereas you are concerned about client-server threading errors. However, the principles are the same and you should be able to adapt the GUI Effect Checker to your needs with relatively few changes.
There is a paper that discusses case studies using the GUI Effect Checker.
An alternative is to adapt a bug finder for finding errors in multithreaded applications. Unlike the GUI Effect Checker, it does not give a guarantee that there are no threading bugs. However, it is effective in practice, and it does not require you to write any annotations in your program.
Finally, the Checker Framework also contains a Lock Checker that ensures correct synchronization. That helps to prevent concurrency errors, though it's orthogonal to your chief concerns about thread safety.
This will assert that method foobar() is called by the correct thread...
SomeType foobar(...) {
assert(Thread.currentThread() == theCorrectThread);
...
}
...If, somewhere in your code prior to the first foobar() call you have set
Thread theCorrectThread = new Thread(...);
but I would prefer something with static checking similar to #Nullable
I know very little about annotations myself. I know that they can be used to attach meta-information to compiled classes, and I know that the program can obtain that information at run-time by calling methods of the Class object, but if there's any way an annotation can define compile-time behavior, that's beyond my ken.
Probably a moot point anyway. When the compiler is processing a .java file, there is no way for it to tell what thread or threads might possibly execute the code that it contains.

Monitoring the size of the Netty event loop queues

We've implemented monitoring for the Netty event loop queues in order to understand issues with some of our Netty modules.
The monitor uses the io.netty.util.concurrent.SingleThreadEventExecutor#pendingTasks method, which works for most modules, but for a module that handle a few thousand HTTP requests per second it seem to be hung, or very slow.
I now realize that the docs strictly specify this can be an issue, and I feel pretty lame... so I'm looking for another way to implement this monitor.
You can see the old code here:
https://github.com/outbrain/ob1k/blob/6364187b30cab5b79d64835131d9168c754f3c09/ob1k-core/src/main/java/com/outbrain/ob1k/common/metrics/NettyQueuesGaugeBuilder.java
public static void registerQueueGauges(final MetricFactory factory, final EventLoopGroup elg, final String componentName) {
int index = 0;
for (final EventExecutor eventExecutor : elg) {
if (eventExecutor instanceof SingleThreadEventExecutor) {
final SingleThreadEventExecutor singleExecutor = (SingleThreadEventExecutor) eventExecutor;
factory.registerGauge("EventLoopGroup-" + componentName, "EventLoop-" + index, new Gauge<Integer>() {
#Override
public Integer getValue() {
return singleExecutor.pendingTasks();
}
});
index++;
}
}
}
My question is, is there a better way to monitor the queue sizes?
This can be quite a useful metric, as it can be used to understand latency, and also to be used for applying back-pressure in some cases.
You'd probably need to track the changes as tasks as added and removed from the SingleThreadEventExecutor instances.
To do that you could create a class that wraps and/or extends SingleThreadEventExecutor. Then you'd have an java.util.concurrent.atomic.AtomicInteger that you'd call incrementAndGet() every time a new task is added and decrementAndGet() every time one is removed/finishes.
That AtomicInteger would then give you the current number of pending tasks. You could probably override pendingTasks() to use that value instead (though be careful there - I'm not 100% that wouldn't have side effects).
It would add a bit of overhead to every task being executed, but would make retrieving the number of pending tasks near constant speed.
The downside to this is of course that it's more invasive than what you are doing at the moment, as you'd need to configure your app to use different event executors.
NB. this is just a suggestion on how to work around the issue - I've not specifically done this with Netty. Though I've done this sort of thing with other code in the past.
Now, in 2021, Netty uses JCTools queues internally and pendingTasks() execution is very fast (almost always constant-time), so even than javadoc still declares that this operation is slow, you can use it without any concerns.
Previously the issue was that counting the elements in the queue was a linear operation, but after migration to JCTools library this problem disappeared.

Java + Swing: writing code to coalesce change events

I have this data flow, roughly:
DataGenerator -> DataFormatter -> UI
DataGenerator is something that generates data rapidly; DataFormatter is something that formats it for display purposes; and the UI is just a bunch of Swing elements.
I'd like to make my DataGenerator something like this:
class DataGenerator
{
final private PropertyChangeSupport pcs;
...
public void addPropertyChangeListener(PropertyChangeListener pcl) {
this.pcs.addPropertyChangeListener(pcl);
}
public void removePropertyChangeListener(PropertyChangeListener pcl) {
this.pcs.removePropertyChangeListener(pcl);
}
}
and just call this.pcs.firePropertyChange(...) whenever my data generator has new data; then I can just do dataGenerator.addPropertyListener(listener) where listener is responsible for pushing the change forward to the DataFormatter and then to the UI.
The problem with this approach, is that there are thousands of dataGenerator changes per second (between 10,000 and 60,000 per second depending on my situation), and the computational cost of formatting it for the UI is high enough that it puts an unnecessary load on my CPU; really all I care about visually is at most 10-20 changes per second.
Is there any way to use a similar approach, but coalesce the change events before they get to the DataFormatter? If I receive multiple update events on a single topic, I just care about displaying the latest one, and can skip all the previous ones.
Two ideas:
Aggregate PropertyChangeEvents. Extend PropertyChangeSupport, overwrite public void firePropertyChange(PropertyChangeEvent evt), fire only if last event was fired more than 50ms (or whatever time seems appropriate) ago. (In fact you should overwrite every fire* method or at least the one you use in your scenario to prevent the creation of the PropertyChangeEvent.)
Drop the whole event based approached. 60.000 events per second is a quite high number. In this situation I would poll. It is a conceptual change to MVP where the presenter knows if it is in active state and should poll. With this approach you don't generate thousands of useless events; you can even present the highest possible frames per second, no matter how much data there is. Or you can set the presenter to a fixed rate, let it sleep between refreshes for a certain time, or let it adapt to other circumstances (like CPU load).
I would tend to the second approach.
It sounds like your DataGenerator doing a lot of non-GUI work on the EDT-thread. I would recommend that your DataGenerator extend SwingWorker and by that doing the work in a background thread, implemented in doInBackground. The SwingWorker could then publish intermediate results to the GUI, while you have a process method that receives the last few published chunks on the EDT and update your GUI.
The SwingWorkers process method does coalesce the published chunks, so it will not run once for every published intermediate result.
If you only care of the last result on the EDT you can use this code, that only cares about the last chunk in the list:
#Override
protected void process(List<Integer> chunks) {
// get the *last* chunk, skip the others
doSomethingWith( chunks.get(chunks.size() - 1) );
}
Read more on SwingWorker: Tasks that Have Interim Results.
You could use a ArrayBlockingQueue of size 1, in which you would push your data with offer() function (means if the queue is full, it does nothing)
Then create a ScheduledThreadPoolExecutor which periodically polls the queue.
This way you loose the coupling between generation and display.
Generator -> Queue -> Formatting/Display
Another possibility is to just add the listener to your generator, but instead of directly reacting to the change you just start a timer. So your listener would look like (in sort of pseudo-code since I am too lazy to fire up my IDE or look up the exact method signatures)
Timer timer = new Timer( 100, new ActionListener(){//update the UI in this listener};
public void propertyChange( PropertyChangeEvent event ){
if ( timer.isRunning() ){
timer.restart();
} else {
timer.start();
}
}
This will work unless your data generator keeps on generating data the whole time, or if you want intermediate updates as well. In that case you can just remove the timer.restart() call, or opt for any of the other suggestions in this thread (the polling mechanism, or the SwingWorker)
If you write your own small change listener that has a blocking flag and a timer, you can:
syncronized onChangeRequest() {
if (flag) {
flag = false;
startTimer();
}
}
timerEvent() {
notify all your listeners;
}
I believe there is actually an excellent blocking concurrency flag that could be used but I cannot for the life of me remember what it is called!

In Swing can you post an event to the top of the EDT events queue?

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).

Categories