My strategy for threading issues in a Swing Java app is to divide methods in three types:
- methods that should be accessed by the GUI thread. These methods should never block and may call swing methods. Not thread-safe.
- methods that should be accessed by non-GUI threads. Basically this goes for all (potentially) blocking operations such as disk, database and network access. They should never call swing methods. Not thread-safe.
- methods that could be accessed by both. These methods have to be thread-safe (e.g. synchronized)
I think this is a valid approach for GUI apps, where there are usually only two threads. Cutting up the problem really helps to reduce the “surface area” for race conditions. The caveat of course is that you never accidentally call a method from the wrong thread.
My question is about testing:
Are there testing tools that can help me check that a method is called from the right thread? I know about SwingUtilities.isEventDispatchThread(), but I’m really looking for something using Java annotations or aspect-oriented programming so that I don’t have to insert the same boilerplate code in each and every method of the program.
Thanks for all the tips, here is the solution I came up with in the end. It was easier than I thought. This solution uses both AspectJ and Annotations. It works like this: simply add one of the annotations (defined below) to a method or a class, and a simple check for EDT rule violations will be inserted into it at the beginning. Especially if you mark whole classes like this, you can do a whole lot of testing with only a tiny amount of extra code.
First I downloaded AspectJ and added it to my project (In eclipse you can use AJDT)
Then I defined two new Annotations:
and
After that, I defined the Aspect that does the actual checking:
Now add @EventDispatchThreadOnly or @WorkerThreadOnly to the methods or classes that should be thread-confined. Don’t add anything to thread safe methods.
Finally, Simply run with assertions enabled (JVM option -ea) and you’ll find out soon enough where the violations are, if any.
For reference purposes, here is the solution of Alexander Potochkin, which Mark referred to. It’s a similar approach, but it checks calls to swing methods from your app, instead of calls within your app. Both approaches are complimentary and can be used together.