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

Programming Java threads in the real world, Part 8

Threads in an object-oriented world, thread pools, implementing socket 'accept' loops

  • Print
  • Feedback

Page 2 of 5

The broad categories of messages (synchronous and asynchronous) can themselves be subdivided in various ways. For example, a balking message is one that can't even be initiated. Imagine that you could only open a limited number of database connections at a given moment, and that all the connections were in use. A message that required access to the database could "balk" if it couldn't get the connection. It isn't that it tried to do the operation and failed; rather, it couldn't even initiate the operation to give it a chance to fail.

Another variant on synchronous messages is a timeout. Rather than balking immediately, the method decides to wait for a predetermined amount of time for the resource to become available. If that time expires, the request will fail. (The operation probably never started, but if the operation indeed started, it certainly didn't complete successfully.) In Java, a read from a socket can timeout in this way.

The problem isn't design; it's implementation. Designing asynchronous systems in an object-oriented way isn't particularly difficult. Object-oriented-design notations such as UML (the "Universal Modeling Language") can easily capture notions such as synchronous and asynchronous messages. Implementing these notions in the essentially procedural system mandated by the Java threading model is another matter, however.

The thread-per-method solution

Given an object-oriented design perspective -- a network of objects communicating via messages -- what's the best way to implement an asynchronous message? The most naive way, which is workable in simple situations, is for each asynchronous-message handler to spawn its own thread.

First, let's consider the following synchronous method, which flushes an internal buffer out to a file. (The Reader_Writer lock was discussed last month.)

 import com.holub.asynch.Reader_writer; import
java.io.*;
class Synchronous_flush
{
    private final OutputStream  out;
    private Reader_writer       lock = new Reader_writer();
    private byte[]              buffer;
    private int                 length;
    public Synchronous_flush( OutputStream out )
    {   this.out = out;
    }
    //...
    synchronized void flush( ) throws IOException
    {   try
        {   lock.request_write();
            out.write( buffer, 0, length );
            length = 0;
        }
        finally
        {   lock.write_accomplished();
        }
    }
}


This blocking version of flush() presents several problems. For one thing, flush() can block indefinitely while waiting to acquire the reader/writer lock. Moreover, if the OutputStream was a socket connection rather than a file, the write operation itself could take a long time to do. Finally, since flush() is synchronized, the entire object is locked while the flush is in progress, so any thread that tries to call any other synchronized method of Synchronous_flush will block until the flush() completes. This wait could turn into a nested-monitor-lockout situation should the lock not be released.

These problems can be solved by making flush() asynchronous; the flush() method should simply initiate the flush operation and then return immediately. Here's an initial (yet, as you'll soon see, not very successful) attempt:

  • Print
  • Feedback

Resources
  • Links to all previous articles in this series can be found in the "Articles" section of Allen's Web site. You can find downloadable version of all the code in the same place. http://www.holub.com
  • "Sockets programming in JavaA tutorial," Qusay H. Mahmoud (JavaWorld, December 1996) Get up to speed on Java's socket support with this tutorial. http://www.javaworld.com/javaworld/jw-12-1996/jw-12-sockets.html
  • "Write your own threaded discussion forumThe communications and server components, Part 2," Michael Shoffner (JavaWorld, March 1997). http://www.javaworld.com/javaworld/jw-03-1997/jw-03-step.html
  • Java Network Programming, Elliotte Rusty Harold (O'Reilly, 1997). http://www1.fatbrain.com/asp/bookinfo/bookinfo.asp?theisbn=1565922271
  • Design Patterns Elements of Reusable Object-Oriented Software, Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (Addison Wesley, 1994). The Command design pattern is presented. This book is essential reading for any object-oriented designer. http://www1.fatbrain.com/asp/bookinfo/bookinfo.asp?theisbn=0201633612