I have an AnimationTimer, that I use as an infinite loop like this:
animator = new AnimationTimer(){
#Override
public void handle(long now) {
// Update
Game.simulationStep();
// Render
Game.render();
}
}
};
animator.start();
The handle function is called 60 times a second, updates a small Game and renders some views in a scenegraph.
What I´m asking myself is, if when I have Events like a button click, will the code of the event be executed after a loop iteration is done?
Or is it multithreaded?
The thing is, I have a List of GameObjects which can be manipulated by the event (removing GameObjects by button click) but also by the logic in simulationStep.
It could be problematic, if the event removes GameObjects from that List, while simulationStep() is doing something with the Objects in the List.
The answer depends not on the code you provide but on your other code.
If the code is responding to events originating in the JavaFX framework (like a button press), then you don't need to worry, because those events are also on the JavaFX thread, the same as the animation timer.
You only need to worry if the event originates on a different thread outside of JavaFX. For example, an incoming chat message from a network chat client, or an AI loop that you are running on your own thread.
Also, you shouldn't use property listeners and bindings that might change values on another thread. For example, don't modify from another thread an observable list that is used to back a list view. The internal implementation of the observer and binding features assumes that the properties and listeners are all used on a single thread. Again, that is only something to worry about if your code is actually multi-threaded.
If you do really have multi-threaded code with events originating from other threads, use JavaFX concurrency, e.g. Task and/or Platform.runLater. Possibly in conjunction with a queue as in Seph's answer as demonstrated (somewhat), by this multi-threaded JavaFX logging framework using a queue. However, usually a separate queue is not required, because Platform.runLater will add runnables to a built-in queue that JavaFX maintains for stuff to be run on the JavaFX thread later.
For your specific concern:
I have a List of GameObjects which can be manipulated by the event (removing GameObjects by button click) but also by the logic in simulationStep. It could be problematic, if the event removes GameObjects from that List, while simulationStep() is doing something with the Objects in the List.
No. It will not be problematic. Everything is running on a single thread, the GameObjects cannot be removed by button click while simulationStep() is running, because the click handler and the simulationStep cannot be running at the same time.
A good summary of different options for executing periodic events and when and when not to involve multiple threads, plus how to handle them if they are used, is in Slaw's answer to:
JavaFX periodic background task
I advise reading the JavaFX architecture overview sections on the Glass Windowing Toolkit, Threads, and Pulse (twice). The document explains how the JavaFX system works with respect to threading, event processing, and pulse handling (the AnimationTimer handle method is triggered by a pulse).
AnimationTimer is not multithreaded and the handle() method runs on the JavaFX application thread, so I guess if you put an infinite loop or a blocking call inside handle(), it freezes the application. Answering your question, unless you have some behaviour that executes on other threads, it'll work fine.
Here's a related thread: Is AnimationTimer running in its own thread?
You can add the events to a queue and process that queue first in your animation timer. This should avoid anytime of concurrency or race condition issues you may be concerned about without hurting anything if they do not actually exist.
animator = new AnimationTimer(){
#Override
public void handle(long now) {
//Process
Game.processEvents();
// Update
Game.simulationStep();
// Render
Game.render();
}
}
};
animator.start();
Related
At the moment, I am working on a version of Conway's Game of Life for my own amusement. Up to this point, everything has gone smoothly, but just as I was testing some of the final parts, I noticed an irritating error. The main body of the code takes place inside of a while loop that is controlled by the number of 'generations' of the game the user would like see. While this loop is executing, the JFrame's red X refuses to respond and I am at a loss as to why this is.
Area where I am encountering this issue:
public void run(int steps) throws InterruptedException{
int a = 0;
do{
step();
myDisp.update(myDisp.getGraphics());
Thread.sleep(delay);
a++;
}while(a < steps);
}
I would suggest you to put this kind of processing in a separate thread.
As long as you keep it in the main body of your code, Swing components will not respond to any user interaction as long as the loop is running.
In this page you can find some good practices regarding asynchronous operations in Swing applications. I would like to highlight one of the topics:
Rule #2: do not run time-consuming operations on the event thread.
I'll keep repeating this: Swing uses a single thread for all GUI events. If your event handler is uploading a multi-megabyte file across the net, those events will be delayed until you're done. There is a balancing act involved with this rule: some operations (such as getting the size of a file) are so fast that they won't interrupt the user. However, that's not a reason to be cavalier, because some day your user will be getting the size of a file that resides on a fileserver that has an intermittent network connection.
This other page also shows an example of how to handle long-running tasks in a Swing application. You may also want to have a look at the SwingWorker class.
By default your while loop will be executing on the Event Dispatch Thread (EDT), which handles all GUI operations. You should never execute long running tasks on the EDT for this reason - the GUI will lock up, since you're not giving it any free time to handle user input! However, you must execute any code that touches the GUI on the EDT. There's a special method, SwingUtilities.invokeLater(), that will do this (take a Runnable and invoke it on the EDT.)
So in your example you would create a new thread and execute it, this thread would contain your while loop, and the myDisp.update() call would be wrapped in the above method to ensure it was still on the EDT. The alternative (neater) solution is to use a SwingWorker, which provides a nicer interface for accomplishing the same thing.
Your long-running while loop is running on the Swing Event Dispatch Thread or EDT, typing it up, and preventing all Swing graphics and user interactions. Solution: use a background thread for your long-running tasks.
Please read: Lesson: Concurrency in Swing
for more details on this and for how to use a SwingWorker.
I'm student and I'm working on project with few of my friends. My task is to make something like class library. Classes in this library should provide API for my friend who must make GUI part of application. GUI could be made by any toolkit (Swing, JavaFX, SWT, AWT, all should work, in fact, it should work even if there is no GUI). I need to make class that waits for data to arrive from network. I don't know when data will arrive, and UI must be responsive during waiting, so I put that in different thread. Now problem is how to make GUI respond when data arrive. Well, I tought that this is asynchronous event and GUI should register event handlers, and I should call that methods when event happens. I proposed this solution:
interface DataArrivedListener{
void dataArrived(String data);
}
class Waiter{
private DataArrivedListener dal;
public void setDataArrivedListener(DataArrivedListener dal){
this.dal = dal;
}
void someMethodThatWaitsForData(){
// some code goes here
data = bufRdr.readLine();
//now goes important line:
dal.dataArrived(data);
// other code goes here
}
}
My question is:
Should I replace "important" line with something like this:
java.awt.EventQueue.invokeLater(new Runnable(){
#Override
public void run(){
dal.dataArrived(data);
}
});
Or something like:
javafx.Platform.runLater(new Runnable(){
#Override
public void run(){
dal.dataArrived(data);
}
});
Or maybe I should do something completely different?
Problem is that I'm not sure which of this will work for any type of UI. If it's GUI, dataArrived() could potentialy make changes to GUI and no matter what type of GUI it is, this changes should be drawn on screen properly. I also think that it is better if I do "invoke this code later" so that my someMethodThatWaitsForData() method could trigger event and continue on with it's on work.
I appreciate your help.
Here's an Event Listener article I wrote a while back. The article explains how you write your own event listeners.
You're correct in that you want to write your own event listeners if you want your library to work with any GUI.
I'm most familiar with Swing, so yes, you'll have GUI code that looks like this:
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent event){
dal.buttonPressed(data);
}
});
If you want it to be completely agnostic to what GUI is being used the only real solution is to let the receiver handle it in dataArrived. Since every toolkit has its own implementation all you can really do to make it work with any toolkit is to disregard it. Otherwise what you will actually end up with is a list of "supported toolkits" and a case for each one.
If you just want dataArrived to be executed away from someMethodThatWaitsForData then you could make your own dispatch thread or make a new thread each time.
If you want to be truly independent of any front-end system, I would recommend creating two threads. The first is your Waiter, which will just listen for events and put them into a Queue of some sort (see the "All Known Implementing Classes" section). The second will invoke the data listener or listeners whenever the queue is not empty.
The concept of invoking a Runnable in the background is kind of deprecated since the invention of the concurrent package. The main reason that this was done in earlier days, is that the GUI code needs to be executed in a different thread, to guarantee that it stays responsive, even if the main thread is busy doing some calculations, but actual multi-threading was still in its very early days. The resulting invokeLater concept works, but comes with a strong creation overhead. This is especially annoying if you frequently have to do minor things, but each time you need to create an entire new Runnable, just to get that event into the Swing thread.
A more modern approach should use a thread-safe list, like a LinkedBlockingQueue. In this case any thread can just throw the event into the queue, and other listener/GUI-Event-handlers can take them out asynchronously, without the need of synchronization or background Runnables.
Example:
You initialize a new Button that does some heavy calculation once it is pressed.
In the GUI thread the following method is called once the button is clicked:
void onClick() {
executor.submit(this.onClickAction);
}
Where executor is an ExecutorService and the onClickAction a Runnable. As the onClickAction is a Runnable that was submitted once during Button creation, no new memory is accessed here. Let's see what this Runnable actually does:
void run() {
final MyData data = doSomeHeavyCalculation();
dispatcher.dispatch(myListeners, data);
}
The dispatcher is internally using the LinkedBlockingQueue as mentioned above (the Executor uses one internally as well btw), where myListeners is a fixed (concurrent) List of listeners and data the Object to dispatch. On the LinkedBlockingQueue several threads are waiting using the take() method. Now one is woken up as of the new event and does the following:
while (true) {
nextEvent = eventQueue.take();
for (EventTarget target : nextEvent.listeners) {
target.update(nextEvent.data);
}
}
The general idea behind all this, is that for once you utilize all cores for your code, and in addition you keep the amount of objects generated as low as possible (some more optimizations are possible, this is just demo code). Especially you do not need to instantiate new Runnables from scratch for frequent events, which comes with a certain overhead. The drawback is that the code using this kind of GUI model needs to deal with the fact that multi-threading is happening all the time. This is not difficult using the tools Java gives to you, but it is an entire different way of designing your code in the first place.
I have a thread that does display updates on my JFrame by using SwingUtilities.invokeLater. The thread's speed is adjustable, and when it set to full speed (no sleeping between updates), my program gets slowed down badly. I guess the problem is my thread is generating too much SwingUtilities.invokeLater events that JFrame's thread can not consume. So is there anything I can do on my thread to remove previously added but not consumed events? Or should I use some other ways to update JFrame without using SwingUtilities.invokeLater?
Thanks in advance.
This might be a perfect job for SwingWorker. You can publish incremental updates, and SwingWorker will batch them to solve the performance problem:
Because the process method is invoked asynchronously on the Event Dispatch Thread multiple invocations to the publish method might occur before the process method is executed. For performance purposes all these invocations are coalesced into one invocation with concatenated arguments.
The code you want to run on the EDT, you add by implementing process(). The list of updates is passed to you in the argument.
It sounds like you want to avoid saturating the event dispatch thread. The class javax.swing.Timer, discussed in How to Use Swing Timers, includes setCoalesce(), which "coalesces multiple pending ActionEvent firings." It may an alternative way to pace your updates.
As mentioned here, SwingWorker is limited to 33 Hz.
Can you use a simple repaint()? The advantage of that is that multiple calls are merged into one.
(Elaboration added)
Let's say you are constantly updating your GPS location and displaying it in two text fields. Your thread to do the updating:
run() {
while (keepGoing) {
Point myLocation = computeMyLocation();
locationModel.setLocation(myLocation);
locationComponent.repaint();
}
}
then, in MyLocationComponent
#Override
public void paintComponent(Graphics g) {
Point myLocation = locationModel.getLocation();
// you'd really want a NumberFormat
latitudeTextArea.setText(String.valueOf(myLocation.y));
longitudeTextArea.setText(String.valueOf(myLocation.x));
super.paintComponent(g);
}
The advantage is that this splits the model from the view (if you think of the thread as the controller, this is MVC), and all the threading should work - no need for any invokeLater(). One disadvantage is that your thread needs to know all of the JComponents that need to be updated. In a "real" scenario you'd probably fire events to listeners that trigger the repaints, either from the "controller" (your thread) or from the model.
NOTE: As pointed out by #trashgod, in LocationModel, the getLocation() and setLocation() methods should be synchronized so that updates appear immediately.
I have a java app in which I use a thread. My thread runs every 20 seconds but, when it runs it kind of blocks the UI ... i. e. whenever the thread is running and the user clicks on button on anything on UI it doesnt respond sometimes.
Could anyone tell me a solution to this problem.
in java Swing, any change made to the state of the UI should be done in a single pre-existing thread called the EDT (event-dispatcher thread).
if that's not the case, you typically experience weird glitches / freezes. one of the most common symptom is that part of the UI becomes gray (except since java 1.6, where the ui is still painted like before, but unresponsive).
the good way to go is to use a dedicated method to queue your changes to the UI in the EDT :
SwingUtilities.invokeLater(Runnable toRunInEDT);
note that if you call invokeLater, the runnable is executed after all currently queued event have been dispatched. that means that the next line of code could be executed before the code in the runnable. there is a synchronous version as well (which should not be executed from the EDT):
SwingUtilities.invokeAndWait(Runnable toRunInEDT);
Some additional tips, on top of what edralzar said:
You can use the convenience method SwingUtilities.isEventDispatchThread() to check if code is in fact running on the event dispatch thread. And, like edralzar said, any code that creates GUI components, modifies the state of GUI components or reads the state of GUI components should run on the Event Dispatch Thread.
Another thing to consider, however, is that code running on the EDT should be able to execute rather quickly. So you cannot just solve things by running everything on the event dispatch thread. If you do the following, your GUI will be frozen for five seconds:
SwingUtilities.invokeLater(new Runnable(){
public void run(){
try{
Thread.currentThread().sleep(5000);
}catch(InterruptedException e){
//Ignored in this example
}
}
});
Why is it frozen? Because all GUI events and GUI updates are performed on the EDT, and if the EDT sleeps for 5000 miliseconds, no GUI updates can be performed during that time.
This article might be an interesting read.
Sounds to me like the thread you're referring to (that runs every 20 seconds) is also the thread that governs the UI.
The solution is to separate the two processes onto different threads.
I have a MouseListener Thread where this method is called each time there is a click:
public void mousePressed(MouseEvent event){
//my Logic here
}
Now what happens is that there are so many clicks in little time, while my logic here, takes more time to process. What i was expecting is that further clicks will be discarded and this method will continue on the latest upcoming clicks.
But what is happening that while the logic is processing, the incoming clics are queued and even when clicking is stopped, qued clicks keep calling this mousePressed method, as a result i have multiple delayed executions.
Unfortunatelly i do not have control over the Listener (why it ques and keep sending delayed clicks), so in such a scenario, can you tell me what is the efficient way of handling such that i do not make a que due to delay in my processing.
I think the most obvious way would be using another thread, but i am wondering this might trigger so many threads in little time, or is there any way i can lock just one thread while the rest of clicks just go through empty loop?
Updates: See Phillip's comments as to why this doesn't work for Swing!
It's unfortunate that you don't have access to the eventListener. The ideal solution would be to unregister the callback while it is being executed.
Here's a solution that emulates unregistering the callback function while it is being executed, assuming you want queued clicks to go away:
private AtomicBoolean engaged = new AtomicBoolean(); // thread-safe boolean
public void mousePressed(MouseEvent event){
if (!engaged.get()) {
engaged.set(true);
// your logic here
engaged.set(false);
}
}
The AtomicBoolean acts as a test-and-set lock preventing multiple threads concurrently running the pressed event callback. Queued presses will be dissipated during the lock.
One solution would be to access the component on which the user clicked and disable it during the processing of the MouseListener. This way it doesn't accept new clicks. This would have the additional benefit of giving the user visual feedback that he is not supposed to click on the component at this time.
You can access the component through the MouseEvent:
public void mousePressed(MouseEvent event) {
event.getComponent().setEnabled(false);
try {
// ....
} finally {
event.getComponent().setEnabled(true);
}
In general though you shouldn't do too much computation in the Swing event listener thread, because Swing also needs it for processing other events and painting. You should use separate Threads for doing actual work and just start them in the MouseListener. You can also use an ExecutorService to simplify this.
It would still be a good idea to disable the gui component during the whole computation in order to give the user feedback.
Edit:
This solution of course depends on Swing. Any similar solution depends on the details of your GUI library, so if you use your own GUI library, you are one your own.
You can of course use a general solution involving separate threads for doing the work. I really recommend an ExecutorService here, were you don't need to care about the details and just submit tasks to execute. You can then have a simple volatile boolean variable which indicates whether the action is currently being executed and new clicks should be ignored.