I've put together a simple publish/subscribe pattern to allow multiple JavaFX classes to be dynamically instantiated and run. Each of these classes (a 'subscriber') is meant to visualize data coming from a model (in the model/view/controller sense) which has the role of 'publisher'. Data for visualization comes in the form of immutable objects, and is passed from the model (running in it's own thread) to a 'buffer' (also running in a separate thread) via a LinkedBlockingQueue. The Buffer then re-publishes all of the data from the model by putting it into LinkedBlockingQueues that are being emptied by threads responsible for running JavaFX visualizations.
So, the data path looks like this:
Model produces immutable objects ----(LinkedBlockingQueue)---> Buffer consumes objects and puts them on multiple queues ====(LinkedBlockingQueue) ===> Visualization thread consumes objects, does some pre-processing, and makes data available to a Timeline animation, which periodically updates the chart.
The entry point for the program extends Application, and its start() method builds all the JavaFX GUI components like so:
for (ModelVisualization viz : vizList) {
viz.buildGUI();
new Thread(viz).start();
}
The threads you see being started are the final consumers of the data in the description of the data-path above.
The problem: The visualizations show up and build properly, but nothing in any JavaFX window updates until the model thread goes to sleep. I can use System.err.println()
statements to verify that the data from the model is moving through the various threads without deadlock, and I can see that the visualization threads are consuming everything properly. However, unless the model thread hits a Thread.sleep(100)
or similar, the method associated with the Timeline never runs.
The model thread itself is started in the entry point constructor like so:
Thread simThread = new Thread(new Runnable() {
@Override
public void run() {
model.runSim();
}
});
simThread.setPriority(Thread.MIN_PRIORITY);
simThread.start();
...And only after that is the JavaFX stuff started up with:
launch();
This should, if I understand things correctly, have the model thread running independently of JavaFX. According to my system resource monitor, I have four whole unused cores (using a Core i7 on OSX) when this program is running, so it doesn't look like I'm starved for resources.
I do not know why JavaFX is paralyzed when my model thread is running. Sleeping my model thread is also something I'd like to avoid. Can anyone shed some light on what's going on, or how I might get JavaFX running properly?