Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Modern threading: A Java concurrency primer

Understanding Java threads in a post-JDK 1.4 world

  • Print
  • Feedback

Page 4 of 7

Testing concurrent programs

Ten years ago on JavaWorld, Dave Dyer noted that the Java language had one feature so "pervasively used incorrectly" that he ranked it as a serious design flaw. That feature was multithreading.

Dyer's comment highlights the challenge of testing multithreaded programs. When you can no longer easily specify the output of a program in terms of a definite sequence of characters, there will be an impact on how effectively you can test your threaded code.

The correct starting point to resolving the intrinsic difficulties of concurrent programming was well stated by Heinz Kabutz in his Java Specialist newsletter: recognize that concurrency is a topic that you should understand and study it systematically. There are of course tools such as diagramming techniques and formal languages that will help. But the first step is to sharpen your intuition by practicing with simple programs like FirstThreadingExample in Listing 1. Next, learn as much as you can about threading fundamentals like these:

 

When to use Runnable

Object orientation in Java defines singly inherited classes, which has consequences for multithreading coding. To this point, I have only described a use for Thread that was based on subclasses with an overridden run(). In an object design that already involved inheritance, this simply wouldn't work. You cannot simultaneously inherit from RenderedObject or ProductionLine or MessageQueue alongside Thread!

This constraint affects many areas of Java, not just multithreading. Fortunately, there's a classical solution for the problem, in the form of the Runnable interface. As explained by Jeff Friesen in his 2002 introduction to threading, the Runnable interface is made for situations where subclassing Thread isn't possible:

The Runnable interface declares a single method signature: void run();. That signature is identical to Thread's run() method signature and serves as a thread's entry of execution. Because Runnable is an interface, any class can implement that interface by attaching an implements clause to the class header and by providing an appropriate run() method. At execution time, program code can create an object, or runnable, from that class and pass the runnable's reference to an appropriate Thread constructor.

So for those classes that cannot extend Thread, you must create a runnable to take advantage of multithreading. Semantically, if you're doing system-level programming and your class is in an is-a relation to Thread, then you should subclass directly from Thread. But most application-level use of multithreading relies on composition, and thus defines a Runnable compatible with the application's class diagram. Fortunately, it takes only an extra line or two to code using the Runnable interface, as shown in Listing 3 below.

  • Print
  • Feedback

Resources

Threads programming

Thread synchronization

Locks and monitors

Testing and debugging threads

Threads & alternatives