This is related to an earlier question I asked, where the answer was:
If a field is accessed by multiple
threads, it should be volatile or
final, or accessed only with
synchronized blocks. Otherwise,
assigned values may not be visible to
other threads.
In addition anything that manipulates pixels on screen should be run from the event dispatch thread although this is handled transparently when you use repaint / paint.
Therefore, by my understanding, we need worry about the memory model for something as simple as an animation of a sprite moving across the screen.
My question is, is this understanding correct, and Sun tutorial examples eg TumbleItem (source) incorrect?
You know, I think you may have a point here. The TumbleItem code uses worker.isDone() to find out whether the work has been completed. However, I don't think this causes a full "synchronize".
My reading of the JDK 1.6 code is that SwingWorker.isDone() uses FutureTask which in turn uses a Sync object with a volatile state attribute. The execution path for isDone() doesn't seem to involve a synchronized method or block.
I'm not a real expert on the new concurrent classes, but I think the TumbleItem should be calling worker.get() at some point to guarantee proper synchronization.
EDIT: I'm referring to the EDT's use of the img array that is populated by the worker. However, it also appears there is an issue with the EDT's use of the initialization parameters, as noted by #The Feast.
typically:
a worker thread does some calculation and reaches some results.
it inserts an event in the event queue
the event thread retrieves the event and process it
during the process the results are accessed.
proper synchronization has been done in step(2) and (3). that's why the results in step(1) can be visible in step(4). Think how you would implement the event queue, and you'll see.
You can use the ThreadCheckingRepaintManager to help you find when you violate the EDT part (not a direct answer to your question, but helpful none the less :-).
I'm not sure what you mean about the Sun tutorial being incorrect?
The animation is done by using a Swing Timer. When the Timer fires the code is executed on the EDT which means it is following the Swing guidelines.
Edit:
Yes your understanding is correct, technically you should worry about the memory model.
And yes, the "offset" is technically updated in two different threads:
a) the default thread when the applet get loaded
b) the EDT "once" the animation is started.
However in my mind (and I may tend to simplify things), when the applet is loaded code is executing on a single thread and all that is happening is that the offset value is simply being initialized. Since only a single Thread is running you shouldn't have to worry about it being updated from multiple threads at the same time.
Now, once the animation has started we have a different situation as this value is used by the GUI to control the animation and therefore should only ever be updated by code on the EDT.
The tutorial says "Swing components should be created, queried, and manipulated on the event-dispatching thread", but we have not yet started to do anything with the Swing components so I don't think it is a problem, but I am no Thread expert.
Related
I've recently started learning and exploring the basics of GUI programming in Java.
Having been programming for a while I have only done backend work or work and as a result the closest I've gotten to user interfaces is the command console (embarrassing I know).
I'm using Swing and as far as I can gather that means by extension I am also using AWT.
My question is based on this piece of code:
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new frame.setVisible(true);
}
} );
I have been researching this for a while as I wanted to fully understand this strange piece of code and have come across the term 'Event-Dispatching Thread' multiple times. Correct me if I'm wrong but as I understand it; it has to do with using multiple threads and how Java Swing interprets those threads. I gather as well that the above code is used to make sure all the threads are 'safe' before it creates the window, hence the invokeLater?
I have read that:
"You can only call methods that operate on the frame from the Event-Dispatching Thread"
and that only under certain circumstances can you call methods that operate on the frame from the main method.
Can somebody please clarify to me what exactly the Event-Dispatching Thread is?
How it relates to multiple threads of execution and how those threads are not safe to be called from the main method? Also why do we need this invokeLater?
Can we not just create the window as any other object?
I've hit a bit of a road block in my research as I'm not grasping these relations and ideas.
A side note is that I like to base my knowledge on in-depth understanding as I believe this leads to the best overall outcome and as a result the best programs. If I understand in-depth how something works then you can use the tips and tweaks effectively rather than just parroting them back in to code, so please don't be afraid to give me some extra in-depth explanations and broaden my knowledge.
Thank you.
The event dispatch thread is a special thread that is managed by AWT. Basically, it is a thread that runs in an infinite loop, processing events.
The java.awt.EventQueue.invokeLater and javax.swing.SwingUtilities.invokeLater methods are a way to provide code that will run on the event queue. Writing a UI framework that is safe in a multithreading environment is very difficult so the AWT authors decided that they would only allow operations on GUI objects to occur on a single special thread. All event handlers will execute on this thread and all code that modifies the GUI should also operate on this thread.
Now AWT does not usually check that you are not issuing GUI commands from another thread (The WPF framework for C# does do this), meaning it's possible to write a lot of code and be pretty much agnostic to this and not run into any problems. But this can lead to undefined behavior, so the best thing to do, is to always ensure that GUI code runs on the event dispatch thread. invokeLater provides a mechanism to do this.
A classic example is that you need to run a long running operation like downloading a file. So you launch a thread to perform this action then, when it is completed, you use invokeLater to update the UI. If you didn't use invokeLater and instead you just updated the UI directly, you might have a race condition and undefined behavior could occur.
Wikipedia has more information
Also, if you are curious why the AWT authors don't just make the toolkit multithreaded, here is a good article.
EventDispatchThread (EDT) is special thread reserved only for Swing GUI and *Swing's related events e.g. create/change/update Swing JComponents, more for asked questions here and here
all output to the GUI from BackGround Tasks, Runnable#Thread must be wrapped into invokeLater(), from synchronized Objects into invokeAndWait();
I am relatively new to game development. I have been developing games and studying game development for 2-3 months now. I use Java.
I have always used Swing for my graphics (aka, the entire game is displayed on a JPanel, using a Graphics2D object). I had no trouble with this up until now.
Very recently, I came across a problem in my most recent project. Some method has problems with being called in consistent time intervals (sometimes it runs every 15-16 milliseconds, as it should, and sometimes it starts to run every 3000 (!) milliseconds).
I did some frustrating debugging and some research, and found out that the reason this happens is probably because I'm not handling Swing and threads right.
My entrie game loop runs inside the run() method of a thread (which is not the EDT). So I'm modifying Swing elements outside of the EDT all of the time. Obviously this was bound to cause problems.
When I found out this was the problem was, I thought:
"Hey, I'll simply use SwingUtilities.invokeLater() in order to run the gameloop inside the EDT!"
But then I remembered, that just as it's 'forbidden' to manipulate Swing elements outside of the EDT, it's also problematic to manipulate non-Swing objects from inside the EDT (I think... is this correct?).
If so, then I have no idea how to develop games in Java using Swing without running into weird problems.
My question is:
How can I develop games safely, using Swing? What would be good guidelines for me to be strict about in order to avoid problems involving Swing and threading? Any instructions every game developer who uses Swing should know?
This is very important for me to understand, since I really want to progress with game development using Java, but if I won't understand this, I'm always going to run into weird problems and won't be able to progress.
Thank you for your help
As long as you don't modify anything but the graphics drawn on the panel, you should be ok most of the time. Just like a single non-EDT thread works most of the time. As long as you don't add or remove any gui elements, don't resize anything, don't hide anything etc., Swing won't fiddle with its internal details enough to cause race conditions between your thread and the EDT - most of the time.
Even the case that the user minimizes the panel while your non-EDT-code is drawing on it will not cause crashes - the panel will probably throw away its old graphics context and start working with a new one, but the old context will remain valid until you release it (this is different from C++ where a delete invalidates the object immediately, which causes crashes when a different thread still uses a local pointer).
The problem is that if you're using the "i've yet to see a case where it goes wrong, always worked for me" approach, you're relying on undefined behaviour, and your code may start crashing as soon as you update your JVM.
The best thing you can do is set up your GUI on the EDT thread, run your game logic on a different thread, have a timer call repaint() on the panel every 20 ms (or whatever you want your frame rate to be). Then, have a class object that holds everything needed to display the current game state. Within a synchronized code block, let the panel's paint() generate its own copy of the object , and have paint() use the copy while the main thread calulates whatever the game needs. The main thread should use the same synchronized to write to the class object of course. That way, you get the maximum possible separation between the threads.
Just running your whole game thread on the EDT probably won't do, as anything your game does that might take a while will cause the UI to freeze. And anything that will need a lot of UI resources will affect your game logic.
BTW, are you sure your initial problem (long delays every now and then, but not always) isn't a result of garbage collection? I've seen this several times; if you aren't using the parallel garbage collector, GC might run for several 10's of a second and block everything else.
When I start my GUI interfaces, what can happen if I don't use invokeLater?
Does that mean all rest of the GUI paints/updates/etc. will be in the main thread?
Will calling a repaint outside of an invokeLater make all subsequent calls fall into the main thread?
Basically this:
void main()
{
JFrame jmf();
setVisible(jmf);
}
------------- VS -------------
void main()
{
SwingUtilities.invokeLater(new Runnable(){
run(){
JFrame jmf();
setVisible(jmf);
}
}
});
NOTE: In cases with small GUI, I if I don't put the invokeLater it seems to work fine. And in fact the application doesn't terminate although the last line of the main is executed.
I have read quite a few articles on why we should use it pertaining to the fact that Swing is not thread safe (it is single threaded and so on), but I really didn't read the repercussions of not calling invokeLater (partially because of my limited knowledge in Threads)
The reality is, nothing might happen or the world will end. It's next to near impossible to predicate, this is the nature of multi-threaded environments...
Unless you are doing some really dynamic setups, until the a frame is made visible it "should" be okay not to do it within the context of the EDT.
The problem comes down to the fact that different platforms are implemented differently (at the native level). For example, the original requirement for using invokeLater when starting your UI seems to have come from deadlocks on the Sun OS many years back.
I've also seen some issues with Java 7 (but my predecessors idea of the thread was weird to say the least). The general advice is, use invokeLater to create and display your UI. Run all UI code within the context of the EDT
It will also reduce the risk of you having to spend weeks trying to replicate and track down those weird anomalies (by running you all you UI code from within the EDT)
Updated based on comments from the OP
repaint makes a request to the RepaintManager, that makes decisions about what and when something should be paint. It will actually post a "paint" event directly on to the Event Queue, which is then processed by the Event Dispatching Thread, so repaint is actually on (of the few) thread safe methods...
Take a look at
Painting in AWT and Swing
Initial Threads
Will the real Swing Single Threading Rule please stand up?
Why is Swing threading model considered wrong and how should it be?
The general advice would be, you should use invokeLater because that's how the API has been designed, doing anything else is inviting problems...
I tried to make a event dispatcher in Java that will dispatch events as threads. So all the EventListener classes are essentially implemented the Runnable class. Like how firing of events work traditionally, a method in the event dispatcher class loops through a list of EventListeners and then invoke their handler method, except that this time, I invoke these handler as threads by putting the listeners into new Thread(handlerObject).start(). The actual handling is done in the run() method in the EventListener.
So it looks something like:
for(EventListener listener : listenerList) {
if(listener instanceof Runnable)
new Thread(listener).start();
}
So all instructions to handle the event in the listener are put inside the run() method, which will be executed when the thread.start().
But the problem is the threads often go into a situation where one of the threads got stuck somewhere and didn't manage to continue. Sometimes, several threads may also get stuck while some managed to run through all instructions in the run() method in the listener. I looked up and this sounds like what it is called a deadlock.
I tried to put the "synchronized" modifier to all my methods but it still has this problem. I thought the synchronized keyword would simply just queue any threads trying to run a similar method until a current thread running the method has finished. But this doesn't solve the problem still. Why doesn't synchronized solve the problem especially when I already have it on all my methods and it should queue any concurrent access that may potentially cause a deadlock? I didn't use any wait() or notify() methods. Just a simple event dispatcher that attempts to run its event listener as a thread.
I am pretty new to threads but have found it very difficult to even debug it because I don't know where has gone wrong.
Thanks for any help.
Deadlock is something along the lines of this:
A needs iron to make tools, asks B for
iron
B needs tools to make iron,
asks A for tools
Neither will complete. Just because you've put the syncronized key word around them does not guarantee that you're going to run into a logical impossibility. You have to judge when one thing will be able to move forward and when it won't.
Never just add synchronized to all methods, this solves nothing - you will effectively make your program single-threaded.
When you think you have a deadlock, you can take a thread dump and analyze the output to understand what each thread is executing, which locks (if any) they are holding, what locks they are waiting for, etc.
Unfortunately without specific code or understanding the actual synchronization going on in your application, the only advice that can be given is general like this.
I don't know what you mean by 'deadlock despite synchronized keyword'. The `synchronized' keyword doesn't prevent deadlocks. It can cause them, if you have two threads that acquire locks in different orders. Solution: don't.
Your real problem is that you don't understand concurrency well enough to understand why your program is not working, let alone how to solve this. (FWIW - adding synchronized to all of your methods is only making the problem worse.)
I think that your best plan is take time out to do some reading on concurrency in Java. Here are a couple of good references:
The Java Concurrency Tutorial Stream.
Java Concurrency in Practice by Brian Goetz et al.
#wheaties has a micro-explanation of what a deadlock is, and #matt_b offers useful advice on how to diagnose a deadlock. However, these won't help a lot unless you know the right way to design and write your multi-threaded code.
In the past few years I've mostly done UI development in Eclipse, which is very conservative in terms of thread access: any attempt to change a property on a UI widget (e.g., color, text) from outside the UI thread throws an exception.
I am now looking at an existing program in Swing that has a window with a large number of custom widget. There is a separate threads that runs a mutation function for each of these widgets, and the mutation function reads the value of some things (e.g., label colors and values) and writes some (e.g., changes background colors). Note that there is no custom painting involved or anything like that, just a bunch of changes to the sub widgets it contains which are mostly JLabels.
At present, this runs from the separate thread, not from the Swing event thread. This thread goes over all the 400 widgets and calls the mutator on each. The updates seem to work correctly, but the GUI is unresponsive to user input.
If I take the whole thing, which runs for about 0.4 msec from outside the Swing thread and wrap every call to a mutator in an invokeLater or invokeAndWait, the UI is a lot more responsive.
What I'm trying to understand is:
1) Is it sometimes legitimate to make all these calls from outside the Swing thread?
2) What is the impact on the Swing thread and why is the UI less responsive when I call it from outside?
From "Nothing" to intermittent problems to "Everything Broke, pull everyone off to work on the GUI!"
The main (most obvious) visual effect is that if you hold up the GUI thread (like someone presses a button and you do a sleep(5000) or something), your GUI won't repaint. It can't because you are holding onto the only thread it's allowed to pass you! This makes people think Java is really slow. It's not bad, but it's easy enough to program that a lot of people who don't bother researching practices like this have produced shipping products.
The next biggest problem is that when you are drawing the screen in another thread (like the one passed to main), it can have strange behavior. Swing is already too picky about how you render your frames--take out threading as a variable!
Finally, rarely (or often if you are calling a swing component in a tight loop on the wrong thread) you can get thread collisions. If that happens an exception may be thrown (or not) and something will probably render wrong, but it may not be obvious.
1) Is it sometimes legitimate to make all these calls from outside the Swing thread?
There are a few exceptions (setting the text value of a text field, for example, does automatic EDT proxying for you) - but there are no situations where it is better to do so. If you are performing lots of updates, you can do them all in a single EDT call (a single call to invokeLater()) instead of individual calls - but even that sort of batching very rarely helps things. Long and short: Perform operations on Swing components from the EDT. That includes reads and writes.
2) What is the impact on the Swing thread and why is the UI less responsive when I call it from outside?
Well, the EDT is responsible for updating the GUI. If you call from outside, it isn't 'less responsive' - it's that the actual low level system calls that update the user interface don't occur (at all). What is probably happening in your app is that the original developers are getting lucky and changing state in the swing component without creating a really nasty race condition. Then some other event is causing a repaint to occur on the EDT, which results in the component being updated. This may appear to be a 'lack of responsiveness' - but what's really happening is a 'lack of screen refresh'.
The EDT is just a regular thread, but it is a bit special in that it runs in a tight loop that processes GUI related signals (draw commands, for example). The semantecs of posting these types of commands on the EDT is really, really different from what we typically think of as Java threading (it involves submitting operations to a message pump).
Long and short - all those Javadocs that say 'only interact with Swing objects on the EDT' are written for a reason. Don't mess with it. If you want to do background processing, fine - but you are responsible for proxying the interaction with the J* components back onto the EDT (most generally using invokeLater() ).
There really are no exceptions. Kevin is partially correct - the JTextComponent.setText() is advertised as thread safe. However, looking at the 1.6 code, it provides synchronization on the document object and does not use the EDT. This is fine, unless another swing component (or something that controls swing components) is listening to the document object. Save yourself the trouble of worrying about it, and just always use the EDT - like Kevin says, there really are no situations (that I'm aware of) to do otherwise.
Hard to say without digging into the code; the behavior is undefined. If your background tasks were long running (> a few seconds), you'd see the opposite effect - using the EDT will make the UI unresponsive while your tasks are running.
Fortunately, it sounds like doing it the right way is working best for you anyway. :)
Sun used to say it was ok to use other threads with components that haven't been realized, but later recanted:
Related stackoverflow question
Check out Sun's UI tutorial on swing and concurrency (I'd post the link, but this is my first answer on stackoverflow0.
The basic problem is that non-thread-safe objects are executed in a multithreaded fashion. Even something as simple as reading a HashMap can be caught in an infinite loop. Because AWT uses locks (badly), you can also end up with deadlocks. However, you are likely to get away with it, although you might find that an updated version of Java suddenly causes you issues on some customer machines.
(BTW: It's AWT's Event Dispatch Thread, not Swing's.)
For (1) as a rule of thumb anything that updates pixels on screen must be called from the Event Dispatching Thread (EDT). Where some JVMs may handle updates from outside the EDT acceptably you should never rely on this working, some machines and different look and feels will not work acceptably. The behaviour is undefined - and this could explain the lack of responsiveness you have seen.