--------------E0FCE998436E2BE7ED79C45D Content-Type: text/plain; charset="us-ascii" Attached article is the latest in the series on multi-threaded Java programming. I haven't yet read it carefully, but I did notice that the reader/writer lock class is significantly less elegant than Peter Welch's Crew class, although performing essentially the same task. And I know which I'd trust not to deadlock, too (shameless plug for Peter's! :-) having seen Peter give a detailed lecture on how to write such things correctly at last year's Wotug21 conference. It's probably about time that the JCSP classes were given a wider audience through such magazines as JavaWorld. Happy reading! http://www.javaworld.com/javaworld/jw-04-1999/jw-04-toolbox.html -- Richard Beton B.Sc. C.Phys. M.Inst.P. Roke Manor Research Limited (http://www.roke.co.uk/) --------- Standard Disclaimer about my own views etc etc -------- --------- My mail client accepts rich text (HTML) mail -------- Welsh Highland Railway: http://www.whr.co.uk/WHR/WHR.html --------------E0FCE998436E2BE7ED79C45D Content-Disposition: inline; filename="jw-04-toolbox.html" Content-Base: "http://www.javaworld.com/javaworld/jw- 04-1999/jw-04-toolbox.html" Content-Location: "http://www.javaworld.com/javaworld/jw- 04-1999/jw-04-toolbox.html" Content-Type: text/html; charset="us-ascii"; name="jw-04-toolbox.html" <HTML> <HEAD> <TITLE>Programming Java threads in the real world, Part 7 - JavaWorld - April 1999</TITLE> <META NAME="description" content="Programming Java threads in the real world, Part 7 -- JavaWorld, April 1999"> <META NAME="keywords" content="JavaWorld, Java, threads, multithreading, AWT "> <META NAME="author" content="Allen Holub"> </HEAD> <BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" ALINK="#FF0000" VLINK="#551a8b"> <center> <table width="525" cellpadding="2" border="0"> <tr> <td colspan="2" align="left" valign="center"> <strong><font size="-1" face="Arial, Helvetica, Sans-serif"> April 1999 </font></strong> </td> <td align="center" valign="bottom"> <IMG width="65" height="20" SRC="/javaworld/icons/javaworld_logo.gif" ALT="JavaWorld"> </td> <td colspan="2" align="right" valign="center"> <strong><font size="-1" face="Arial, Helvetica, Sans-serif"> <a href="/javaworld/common/jw-subscribe.html?article">Get FREE JW e-mail alerts</A> </font></strong> </td> </tr> <tr> <td align="center"><a href="/javaworld/jw-04-1999/index.html"><img border="0" width="74" height="21" src="/javaworld/icons/b-home.gif" alt="[JavaWorld Main Page]"></a></td> <td><a href="/javaworld/search.html"><img border="0" width="107" height="21" src="/javaworld/icons/b-search.gif" alt="[JavaWorld Search]"></a></td> <td><a href="/javaworld/jw-04-1999/index.html#nuts"><img border="0" width="107" height="21" src="/javaworld/icons/b-nuts2.gif" alt="[Nuts & Bolts]"></a></td> <td><a href="/javaworld/jw-04-1999/index.html#news"><img border="0" width="107" height="21" src="/javaworld/icons/b-news.gif" alt="[News & Views]"></a></td> <td><a href="/javaworld/jw-04-1999/index.html#res"><img border="0" width="107" height="21" src="/javaworld/icons/b-jr.gif" alt="[Java Resources]"></a></td> </tr> </table> </center> <CENTER> <TABLE CELLPADDING="0" BORDER="0"> <TR> <TD> <NOLAYER> <IFRAME SRC="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=468x60" width=468 height=60 marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=no><A HREF="http://ad.doubleclick.net/jump/idg.jw.com/archives;sz=468x60"><IMG SRC="http://ad.doubleclick.net/ad/idg.jw.com/archives;sz=468x60" width=468 height=60 ></A></IFRAME> </NOLAYER> <ilayer id=ph1 visibility=hide width=468 height=60></ilayer> <BR CLEAR="ALL"> <center>Click on our Sponsors to help Support <em>JavaWorld</em></center> </TD> </TR> </TABLE> </CENTER><CENTER><IMG WIDTH="437" HEIGHT="29" SRC="/javaworld/icons/cb-toolbox.gif" ALT="Java Toolbox by Alan Holub"></CENTER> <H1 ALIGN="CENTER"> Programming Java threads in the real world, Part 7 </H1> <H3 ALIGN="CENTER"> S Singletons, critical sections, and reader/writer locks </H3> <BLOCKQUOTE> <STRONG>Summary</STRONG><BR> This month's column builds on the preceding installments of the <strong>Java Toolbox</strong> threads series, adding a few more tools to your multithreading arsenal. Columnist Allen Holub looks at reader/writer locks, which let multiple threads safely access a shared resource in an efficient way. (Multiple threads can read from the resource while only one thread at a time can write to it, and reads and writes can't occur at the same time.) He'll also discuss the Singleton pattern, with a focus on implementing it in a multithreaded environment, and <em>critical sections,</em> or blocks of code that can be executed by only one thread at a time. <em>(5,300 words)</em> </BLOCKQUOTE> <CENTER><IMG WIDTH="468" HEIGHT="4" SRC="/javaworld/icons/green.gif"></CENTER><P> <table align="right" cellpadding="0" cellspacing="10" border="0"> <tr><td colspan="2" align="center"> <a href="/javaworld/cgi-bin/jw-mailfriend.cgi?/javaworld/jw-04-1999/jw-04-toolbox.html+Programming_Java_threads_in_the_real_world,_Part_7+Allen_Holub+col"><img border="0" width="31" height="57" src="/javaworld/icons/mailbox2.gif" alt=""></a><br> <font size="-1" face="Arial, Helvetica, Sans-serif"> <a href="/javaworld/cgi-bin/jw-mailfriend.cgi?/javaworld/jw-04-1999/jw-04-toolbox.html+Programming_Java_threads_in_the_real_world,_Part_7+Allen_Holub+col">Mail this<br> article to<br> a friend</a> <P> <TABLE CELLPADDING="0" CELLSPACING="5" BORDER="0"> <TR> <TD BGCOLOR="000000"><img border="0" width="1" height="1" src="/javaworld/icons/black.gif" alt=""></TD> <TD> <font size="-1" face="Arial, Helvetica, Sans-serif"> <center><strong>Supporting<BR>sponsors</strong></center> <p> <!-- BEGIN DART 125x125 BANNERS (INTERNET EXPLORER IFRAMES) --> <NOLAYER> <IFRAME SRC="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=125x125;tile=1" height=125 width=125 marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=no><A HREF="http://ad.doubleclick.net/jump/idg.jw.com/archives;sz=125x125;tile=1"><IMG SRC="http://ad.doubleclick.net/ad/idg.jw.com/archives;sz=125x125;tile=1" height=125 width=125></A></IFRAME> <P> <IFRAME SRC="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=125x125;tile=2" height=125 width=125 marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=no><A HREF="http://ad.doubleclick.net/jump/idg.jw.com/archives;sz=125x125;tile=2"><IMG SRC="http://ad.doubleclick.net/ad/idg.jw.com/archives;sz=125x125;tile=2" height=125 width=125></A></IFRAME> <P> </NOLAYER> <ilayer id=ph2 visibility=hide height=125 width=125></ilayer> <P> <ilayer id=ph3 visibility=hide height=125 width=125></ilayer> <!-- END DART 125x125 BANNERS (INTERNET EXPLORER IFRAMES) --> <P> <img border="0" width="125" height="1" src="/javaworld/icons/black.gif" alt=""> <!-- <P> <A href="http://ad.doubleclick.net/jump/idg.jw.com/sponsor-button/left1;sz=125x125"><IMG src="http://ad.doubleclick.net/ad/idg.jw.com/sponsor-button/left1;sz=125x125" vspace="4" border="0" height="125" width="125"></A> --> <P> <A href="http://ad.doubleclick.net/jump/idg.jw.com/sponsor-button/left2;sz=125x125"><IMG src="http://ad.doubleclick.net/ad/idg.jw.com/sponsor-button/left2;sz=125x125" vspace="4" border="0" height="125" width="125"></A> </font> </TD> </TR> </TABLE> </td></tr></table> <!-- begin body text --> <IMG ALIGN="LEFT" width="24" height="29" SRC="/javaworld/abcs/T.gif" ALT="T">his month I'm going to tie up a few synchronization-related loose ends left over from my previous <strong>Java Toolbox</strong> installments in this series. I'll start out looking at <em>Singletons,</em> or one-of-a-kind objects. These are surprisingly difficult to implement efficiently in a multithreaded environment, but are essential in most programs. (<code>java.awt.Toolkit</code> is an example of a Singleton.) Along the way, I'll also look at <em>critical sections,</em> or blocks of code -- as compared to objects -- that can be locked. <P> I'll finish up with a completely unrelated topic: <em>reader/writer locks,</em> which give you efficient, thread-safe access to read/write resources such as data structures and files. Reader/writer locks are simple enough to implement that I didn't want to devote an entire column to them, but they're essential in any multithreaded program that performs I/O operations, so I wanted to include them in the present series of articles. Reader/writer locks combined with the various semaphores and locks I've presented in previous installments of this series comprise a reasonably complete toolkit for solving thread-related synchronization problems. <P> <FONT SIZE="+1"><STRONG>Critical sections, Singletons, and the Class object</STRONG></FONT><BR> So far in this series I've been concentrating on the <em>monitor</em> -- a means of locking an entire object while a body of code is being executed. The other essential sort of lock you should be aware of is the <em>critical section.</em> Critical sections are essential in implementing one-time initialization code when that code can be accessed from multiple threads. <P> A critical section is a chunk of code that can be executed by only one thread at a time. Compare this notion with a normal <code>synchronized</code> code block -- a <em>monitor</em> -- which is basically an exclusion semaphore that guards an entire object. Several threads can simultaneously execute a <code>synchronized</code> method, but only if the objects that are receiving the associated messages are different. In a critical section, the code itself is locked, not the object. Only one thread can be in the critical section at a time, even if the receiving objects are different. The mutex that guards a monitor is an object-level mutex; the mutex that guards a critical section is effectively a class-level mutex. Think of it this way: the code is defined in the class, not the object, so when you're locking the code itself, you're locking the entire class of objects. (By the way, I've seen authors get this wrong in print when they call a block of code inside a nonstatic method a "critical section." A block of code in a nonstatic method is part of the object's monitor; it is <em>not</em> a critical section.) <P> <strong>Static members</strong></br> In Java, the notion of a critical section is closely tied to that of a static member, so let's start there. Java, like all OO languages, supports two categories of fields and methods: <P> <table bgcolor="#FFFFCC" cellpadding="3" cellspacing="1" border="0"> <tr> <td align="right" bgcolor="#FFFF00" valign="center"><strong>Class variables</strong>:</td> <td align="left" valign="center">variables that control the state of all objects within a class.</td> </tr><tr> <td align="right" bgcolor="#FFFF00" valign="center"><strong>Instance variables</strong>:</td> <td align="left" valign="center">variables that control the state of a single object within a class.</td> </tr> </table> <P> A class variable is implemented in Java by placing a <code>static</code> keyword before its definition. <P> To best explain how the two types of variables are used in practice, an example seems in order. Back in the dark ages (the early 1990s) somebody had the bright idea that every window on a computer screen should use a different color scheme, even within a single application. Magenta backgrounds with yellow borders, turquoise backgrounds with chartreuse borders -- it make your eyes hurt. (The reasoning was that the users would somehow remember the color combinations and more easily identify the windows. Nice theory, but the human mind just doesn't work that way.) In this system, a window's color scheme is an "instance variable": every instance -- every window -- potentially has a different value for its color scheme. <P> Eventually, people came to their senses and made all the windows the same color. Now the color scheme is a "class variable." The entire class of window objects uses the same color scheme. If the scheme changes, then all the windows should change their appearance. <P> You can model the class-level behavior like this: <P> <pre> <a name="Window">class Window // not the AWT window</a> { <a name="Window.foreground"> private static Color foreground = SystemColor.windowText;</a> <a name="Window.background"> private static Color background = SystemColor.window;</a> <a name="Window.change_color_scheme(Color,Color)">synchronized static public change_color_scheme( Color foreground, Color background )</a> { this.foreground = foreground; this.background = background; // code goes here that tells all the extant Window objects to // redraw themselves with the new color scheme. } } </pre> <P> There are several problems with this simplistic approach, however, the first being threading. <P> Java creates a <code>Class</code> class object for every class in your system, and the <code>static</code> fields are members of this <code>Class</code> object. A <code>Class</code> object is a real object: It has methods (declared <code>static</code> in the class definition) and state (defined by the <code>static</code> fields). The <code>Class</code> object also has its own monitor. When you call a <code>synchronized static</code> method, you enter the monitor associated with the <code>Class</code> object. This means that no two <code>synchronized static</code> methods can access the <code>static</code> fields of the class at the same time. You can also lock the <code>Class</code> object explicitly, like this: <P> <pre> synchronized( Window.class ) { // modify static fields here } </pre> <P> Unfortunately, the <code>Class</code>-level monitor is in no way connected to the monitors of the various instances of the object, and a <code>synchronized</code>, but nonstatic, method can also access the <code>static</code> fields. Entering the <code>synchronized</code> nonstatic method does not lock the <code>Class</code> object. Why is this a problem? Well, in the previous example, it would appear to be harmless to omit the <code>static</code> (but not the <code>synchronized</code>) from the definition of <code>change_color_scheme()</code> since the <code>static</code> fields will be modified, even if the modifying method isn't <code>static</code>. Appearances are deceiving, though. If two threads simultaneously send <code>change_color_scheme()</code> messages to two <em>different</em> objects of class <code>Window</code>, a race condition results, and the color scheme will be in an unknown state. In other words, the individual <code>Window</code> objects are locked, but locking a <code>Window</code> object does not lock the corresponding <code>Class</code> object (which contains the class variables), and the <code>static</code> fields are unguarded. Consequently, we have two threads modifying two variables at the same time. <P> After threading, the second problem with the naive implementation is that there's no way to guarantee that all the existing objects stay in synch with changes to the class variables. A sloppy programmer can add an instance method (one that is not <code>static</code>) to the <code>Window</code> class, and that instance method can change the <code>foreground</code> or <code>background</code> fields without notifying the other windows, or even without updating its own color. <P> You can fix both the race-condition and lack-of-update problems by encapsulating the two <code>static</code> fields in a class of their own: <P> <pre> <a name="Color_scheme">class Color_scheme</a> { <a name="Color_scheme.foreground"> private Color foreground = SystemColor.windowText;</a> <a name="Color_scheme.background"> private Color background = SystemColor.window;</a> /*package*/ synchronized change_color_scheme( Color foreground, Color background ) { this.foreground = foreground; this.background = background; // code goes here that tells all the extant Window objects to // redraw themselves with the new color scheme. } } <a name="Window">class Window // not the AWT window</a> { static Scheme color_scheme = new Color_scheme(); static change_color_scheme( Color foreground, Color background ) { scheme.change_color_scheme( foreground, background ); } } </pre> <P> Now there's no way to modify the foreground or background color without notifying the other windows. Note that this is one of the few cases in which you must use package access rather than an inner class. Had <code>Color_scheme</code> been an inner class of <code>Window</code>, direct access to <code>foreground</code> and <code>background</code> would still be possible from methods of <code>Window</code>. This approach also has the advantage of making the monitor that controls the <code>Color_scheme</code> more visible -- it's obviously the one associated with the explicit <code>Color_scheme</code> object, not the one associated with the <code>Window</code>. <P> <FONT SIZE="+1"><STRONG>Singletons</STRONG></FONT><BR> There's another problem with the earlier code, however. We really want only one <code>Color_scheme</code> to exist, ever. In the earlier code, I've done it accidentally by making the reference <code>static</code> and only calling <code>new</code> once, but I'd really like to guarantee that only one instance of the object can exist. The Gang-of-Four "Singleton" pattern describes exactly this situation. Two excerpts from the Gang-of-Four book are relevant. The "Intent" section in the Gang-of-Four book's chapter on Singleton states: <P> <blockquote> <em>Ensure a class only has one instance, and provide a global point of access to it.</em> </blockquote> <P> and the "Consequences" section says: <P> <a name=singleton_consequences> <blockquote> <em>[Singleton] permits a variable number of instances. The pattern makes it easy to change your mind and allow more than one instance of the Singleton class. Moreover, you can use the same approach to control the number of instances that the application uses. Only the [Instance] operation that grants access ot the Singleton instance needs to change.</em> </blockquote> </a> <P> That excerpt from the "Consequences" section is interesting because it allows a <code>Class</code> object to be considered a Singleton, even though there's more than one instance of the <code>Class</code> class in the program. It's guaranteed that there will be only a single instance of <code>Class</code> for a given class, so it's a Singleton: <code>Some_class.class</code> (the "operation that grants access") always evaluates to the <em>same</em> <code>Class</code> object. The <code>static</code> fields and methods, since they are members of the <code>Class</code> object, define the state and methods of the Singleton object as well. Exploiting this reasoning, I can ensure that only one instance of the <code>Color_scheme</code> exists by moving everything into the <code>Class</code> object (making everything <code>static</code>): <P> <pre> <a name="Color_scheme">class Color_scheme</a> { <a name="Color_scheme.foreground"> private <strong>static</strong> Color foreground = SystemColor.windowText;</a> <a name="Color_scheme.background"> private <strong>static</strong> Color background = SystemColor.window;</a> <strong>private Color_scheme(){}</strong> /*package*/ synchronized <strong>static</strong> change_color_scheme( Color foreground, Color background ) { this.foreground = foreground; this.background = background; // code goes here that tells all the extant Window objects to // redraw themselves with the new color scheme. } } </pre> <P> Note that I've also added a <code>private</code> constructor. A class, all of whose constructors are private, can be created only by a <code>new</code> that's invoked in a method that legitimately has access to the class's other <code>private</code> components. There are no such methods here, so no instances of <code>Color_scheme</code> can actually be created. This guarantees that only one object can exist -- the <code>Class</code> object, a Singleton. <P> I also have to change the <code>Window</code> to use the <code>Class</code> object rather than a specific instance: <P> <pre> <a name="Window">class Window // not the AWT window</a> { // <strong>Note that there's no field here, now.</strong> change_color_scheme( Color foreground, Color background ) { <strong>Color_scheme</strong>.change_color_scheme( foreground, background ); } } </pre> <P> I've eliminated the <code>static</code> field in the <code>Window</code> class and have invoked <code>change_color_scheme()</code> directly through the class. <P> This sort of Singleton -- a class all of whose methods are <code>static</code> -- is called a "Booch utility" (after Grady Booch, who identified the pattern in one of his early books). Java's <code>Math</code> class is a good example of a utility-style Singleton. <P> The problem with the make-everything-<code>static</code> approach to Singleton creation is that all the information needed to create the object must be known at class-load time, and that isn't always possible. Java's <code>Toolkit</code> is a good example. An application must load a different <code>Toolkit</code> than an applet, but a given chunk of code doesn't know whether it's running in an application or an applet until runtime. The actual instance of the toolkit is brought into existence by calling the <code>static</code> method <code>Toolkit.getDefaultToolkit()</code>. The object itself doesn't exist until the method is called the first time. Subsequent calls return a reference to the object that's created by the first call. <P> <strong>Critical sections</strong><br> Bringing a Singleton into existence at runtime (rather than at load-time) is fraught with peril in a multithreaded environment. You can implement the creation function naively as follows: <P> <pre> <a name=".get_instance()">public static synchronized Singleton get_instance()</a> { if( instance == null ) instance = new Singleton(); return instance; } </pre> <P> The <code>static synchronized</code> method forms a <em>critical section</em> -- a block of code that can be executed by only one thread at a time. If <code>get_instance()</code> weren't synchronized, a thread could be preempted after the <code>if</code> statement was processed, but before the <code>instance=new Singleton()</code> was executed. The preempting thread could then call <code>get_instance()</code>, create an instance, and yield. The preempted thread would then wake up, think that there were no instances (because it has already performed the test), and create a second instance of the object. The "critical section" eliminates the multiple-creation problem by preventing any thread from entering <code>get_instance()</code> if any other thread is already inside the method. Any Singleton object can be used to implement a critical section. Here, the <code>Class</code> object whose monitor we're using is itself a Singleton, so by locking this object implicitly when we enter the <code>static</code> method, we prevent other threads from executing the method in parallel. (All <code>synchronized static</code> methods actually are critical sections when you look at them that way.) <P> This strategy of using the <code>Class</code> object's monitor as the critical-section lock doesn't always work out because you lock all the <code>static</code> methods of the class, not just the Singleton-creation method. You can do the same thing with an explicitly declared Singleton lock as follows: <P> <pre> <a name=".lock">private static Object lock = new Object();</a> <a name=".get_instance()">public static Singleton get_instance() // not synchronized</a> { synchronized( lock ) { if( instance == null ) instance = new Singleton(); return instance; } } </pre> <P> This version still assures that only one instance of the Singleton will be created, but it won't interfere with the execution of other static methods. <P> The main problem with this naive approach is efficiency. We acquire the lock every time we call <code>get_instance()</code>, even though the code only needs to be locked the first time the method is called. The solution to this problem is Doug Schmidt's "double-checked locking" strategy. Here's the general pattern: <P> <pre> <a name="Singleton">class Singleton</a> { <a name="Singleton.instance"> private Singleton instance;</a> //... <a name="Singleton.get_instance()"> public static Singleton get_instance() // not synchronized</a> { if( instance == null ) { synchronized( Std.class ) { if( instance == null ) instance = new Singleton(); } } return instance; } } </pre> <P> Most of the time, the object will exist when <code>get_instance()</code> is called, so we won't do any synchronization at all. On the first call, however, <code>instance</code> is <code>null</code>, so we enter the <code>if</code> statement and synchronize explicitly on the <code>Class</code> object to enter a critical section. Now we have to test for <code>instance==null</code> again, because we might have been preempted just after the first <code>if</code> was processed but before the <code>synchronized</code> statement was executed. If <code>instance</code> is <em>still</em> <code>null</code>, then no other thread will be creating the Singleton, and we can create the object safely. <P> <a href="#_listing1_">Listing 1</a> shows you a real-world application of Singleton that compensates for a problem in the design of the <code>System</code> class. A proper OO design <em>never</em> uses public fields except for symbolic constants, and I really mean "constant" here: The exposed field must be immutable, not just <code>final</code>. (An object accessed via a <code>final</code> reference can be modified; an "immutable" object (like a <code>String</code>) can't be modified at all.) This rule applies to both "class" and "instance" variables, and there are no exceptions to this rule. Ever. Period. Strong encapsulation of an object's implementation is so central to what "object orientation" means, that this point is simply not negotiable. If you use public fields, your program just isn't object oriented -- it's some sort of part-OO/part-procedural polyglot, and you will reap virtually none of the real benefits of OO such as improved maintenance. The only legitimate public members of a class are those methods that handle messages defined in your design's dynamic-model. <P> The foregoing notwithstanding, there is one place in the Java packages where instance variables are exposed: <code>System.in</code>, <code>System.out</code>, and <code>System.err</code>. To my mind, this exposure is a serious design flaw: These fields are not <code>Reader</code> or <code>Writer</code> derivatives, so they are not internationalizable. Consequently, you can't use these variables without wrapping them in a <code>Reader</code> or <code>Writer</code>. If <code>System.in</code>, <code>System.out</code>, and <code>System.err</code> had been accessed through "accessor" methods rather than directly, this wrapping could have been done transparently by the (missing) method that returned the I/O stream. This method could have easily been modified to return a <code>PrintWriter</code> rather than a <code>PrintStream</code> without impacting much of the code that used it. As it is, there's a lot of incorrect code out there that uses the three streams directly. <P> <a href="#_listing1_">Listing 1</a> solves the problem (or at least hides it) by using the Singleton pattern. You write to standard output, for example, like this: <code>Std.out().println("Hello world"); </code> The <code>out()</code> method (<a href="#Std.out()">Listing 1, line 33</a>) creates a Singleton <code>PrintWriter</code> wrapper around <code>System.out</code> and returns it. Subsequent calls to <code>Std.out()</code> return the same wrapper object, so you don't have to create a new one every time you need to write a string. <P> Other methods in the class work the same way: <code>Std.err()</code> returns a Singleton <code>PrintWriter</code> that wraps <code>System.err</code>, and <code>Std.in()</code> returns a <code>BufferedReader</code> that wraps <code>System.in</code>. I've also provided a <code>Std.bit_bucket()</code> that returns an implementation of <code>PrintWriter</code> that does nothing. This is occasionally useful for throwing away otherwise undesirable output. For example, you might pass a method a <code>Writer</code> onto which it prints error or status messages. Passing this method <code>Std.bit_bucket()</code> causes the messages to not be printed. <P> Note, by the way, that the <code>Bit_bucket</code> class (<a href="#Std.Bit_bucket">Listing 1, line 61</a>) is <code>private</code>, but it extends <code>PrintWriter</code> -- a <code>public</code> class -- overriding all the methods with no-ops. This notion of a private class implementing a public interface is a useful one. The outside world sees a <code>Bit_bucket</code> object as a <code>Print_writer</code>, knowing nothing about its actual implementation -- not even its class name. Though it doesn't do it here, the <code>private</code> inner class can define a set of methods that comprise a private interface to the outer class. This way the outer-class object can communicate with the inner-class object using methods that nobody else can access. <P> <!-- --------- LISTING 1 (/src/com/holub/tools/Std.java) --------- --> <a name="_listing1_"> <table border=1 cellspacing=0 cellpadding=10> <caption><strong>Listing 1: <em>/src/com/holub/tools/Std.java</em></strong></caption> <tr> <td valign=top> <!-- file: /src/com/holub/tools/Std.java --> <table border=0 cellspacing=0 cellpadding=0><tr><td valign=top align=right><pre> 001 002 003 004 </pre></td> <td valign=top> <pre> package com.holub.tools; import java.io.*; import com.holub.asynch.JDK_11_unloading_bug_fix; </pre> </td></tr> <tr><td></td><td valign=top><pre> /** A convenience class that takes care of wrapping a writer around<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> standard output. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 005 006 007 008 009 010 011 012 013 014 </pre></td> <td valign=top> <pre> <a name="Std">public final class Std</a> { <a name="Std.java.bug_fix"> static{ new JDK_11_unloading_bug_fix(Std.class); }</a> <a name="Std.input"> private static BufferedReader input; //= null</a> <a name="Std.output"> private static PrintWriter output; //= null</a> <a name="Std.error"> private static PrintWriter error; //= null</a> <a name="Std.bit_bucket"> private static PrintWriter bit_bucket; //= null</a> </pre> </td></tr> <tr><td></td><td valign=top><pre> /*******************************************************************<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> A private constructor, prevents anyone from manufacturing an instance. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 015 016 </pre></td> <td valign=top> <pre> <a name="Std.Std()"> private Std(){}</a> </pre> </td></tr> <tr><td></td><td valign=top><pre> /*******************************************************************<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> Get a BufferedReader that wraps System.in </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 </pre></td> <td valign=top> <pre> <a name="Std.in()"> public static BufferedReader in()</a> { if( input == null ) synchronized( Std.class ) { if( input == null ) try { input = new BufferedReader( new InputStreamReader(System.in)); } catch( Exception e ) { throw new Error( e.getMessage() ); } } return input; } </pre> </td></tr> <tr><td></td><td valign=top><pre> /*******************************************************************<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> Get a PrintWriter that wraps System.out. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 033 034 035 036 037 038 039 040 041 </pre></td> <td valign=top> <pre> <a name="Std.out()"> public static PrintWriter out()</a> { if( output == null ) synchronized( Std.class ) { if( output == null ) output = new PrintWriter( System.out, true ); } return output; } </pre> </td></tr> <tr><td></td><td valign=top><pre> /*******************************************************************<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> Get a PrintWriter that wraps System.err. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 042 043 044 045 046 047 048 049 050 051 </pre></td> <td valign=top> <pre> <a name="Std.err()"> public static PrintWriter err()</a> { if( error == null ) synchronized( Std.class ) { if( error == null ) error = new PrintWriter( System.err, true ); } return error; } </pre> </td></tr> <tr><td></td><td valign=top><pre> /*******************************************************************<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> Get an output stream that just discards the characters that are sent to it. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 052 053 054 055 056 057 058 059 060 </pre></td> <td valign=top> <pre> <a name="Std.bit_bucket()"> public static PrintWriter bit_bucket()</a> { if( bit_bucket == null ) synchronized( Std.class ) { if( bit_bucket == null ) bit_bucket = new Bit_bucket(); } return bit_bucket; } </pre> </td></tr> <tr><td></td><td valign=top><pre> /**<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> The Bit_bucket class overrides all methods of PrintWriter to do nothing. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 </pre></td> <td valign=top> <pre> <a name="Std.Bit_bucket"> private static final class Bit_bucket extends PrintWriter</a> { <a name="Std.Bit_bucket.Bit_bucket()"> private Bit_bucket()</a> { super( System.err ); // have to pass it something legal. Is never used. } <a name="Std.Bit_bucket.close()"> public void close() {}</a> <a name="Std.Bit_bucket.flush()"> public void flush() {}</a> <a name="Std.Bit_bucket.print(boolean)"> public void print(boolean b) {}</a> <a name="Std.Bit_bucket.print(char)"> public void print(char c) {}</a> <a name="Std.Bit_bucket.print(char[])"> public void print(char[] s) {}</a> <a name="Std.Bit_bucket.print(double)"> public void print(double d) {}</a> <a name="Std.Bit_bucket.print(float)"> public void print(float f) {}</a> <a name="Std.Bit_bucket.print(int)"> public void print(int i) {}</a> <a name="Std.Bit_bucket.print(long)"> public void print(long l) {}</a> <a name="Std.Bit_bucket.print(Object)"> public void print(Object o) {}</a> <a name="Std.Bit_bucket.print(String)"> public void print(String s) {}</a> <a name="Std.Bit_bucket.println()"> public void println() {}</a> <a name="Std.Bit_bucket.println(boolean)"> public void println(boolean b) {}</a> <a name="Std.Bit_bucket.println(char)"> public void println(char c) {}</a> <a name="Std.Bit_bucket.println(char[])"> public void println(char[] s) {}</a> <a name="Std.Bit_bucket.println(double)"> public void println(double d) {}</a> <a name="Std.Bit_bucket.println(float)"> public void println(float f) {}</a> <a name="Std.Bit_bucket.println(int)"> public void println(int i) {}</a> <a name="Std.Bit_bucket.println(long)"> public void println(long l) {}</a> <a name="Std.Bit_bucket.println(Object)"> public void println(Object o) {}</a> <a name="Std.Bit_bucket.write(char[])"> public void write(char[] buf) {}</a> <a name="Std.Bit_bucket.write(char[],int,int)"> public void write(char[] buf, int off, int len) {}</a> <a name="Std.Bit_bucket.write(int)"> public void write(int c) {}</a> <a name="Std.Bit_bucket.write(String)"> public void write(String buf) {}</a> <a name="Std.Bit_bucket.write(String,int,int)"> public void write(String buf, int off, int len) {}</a> } <a name="Std.Test"> static public class Test</a> { <a name="Std.Test.main(String[])"> static public void main( String[] args ) throws IOException</a> { String s; while( (s = Std.in().readLine()) != null ) { Std.out().println( s ); Std.err().println( s ); Std.bit_bucket().println( s ); } } } } </pre> </td></tr> </table> </td> </tr> </table> </a> <!-- --------- END LISTING 1 --------- --> <P> The final thread-related subtlety is the static initializer block (Listing 1, line <a href="#Std.java.bug_fix">8</a>): <P> <pre> static{ new JDK_11_unloading_bug_fix(Std.class); } </pre> <P> The <code>JDK_11_unloading_bug_fix</code> class in <a href="#_listing2_">Listing 2</a> gets around a bug in the VM released with all versions of JDK 1.1. The VM in those releases was much too aggressive about unloading (and garbage collecting) <code>Class</code> objects: If the only reference to an object of a given class was a self-referential static member of the <code>Class</code> object, then the VM would unload the class from memory, thereby destroying our only copy of the Singleton. The next time someone tried to get an instance, the class would be reloaded and a second instance of the Singleton would be created. Sometimes this behavior did nothing but make the program a little slower. But if the act of creating the Singleton object has side effects (like creating temporary files or opening data-base connections ), this second creation can be a problem. <P> The fix in Listing 2 is a kluge, but it works. I'm counting on the fact that the VM itself keeps around references to potentially active threads. If the current program is not running under a 1.1 version of the JDK <code>System.getProperty("java.version").startsWith("1.1") )</code> is false, nothing at all happens. If version 1.1 is active, the <code>JDK_11_unloading_bug_fix</code>'s constructor creates a <code>Thread</code> derivative whose one field holds a reference to the <code>Class</code> object passed in as an argument. The thread's <code>run()</code> method immediately suspends itself by calling <code>wait()</code>. Since there never will be a <code>notify()</code>, the thread doesn't use up any machine cycles, but since the <code>Thread</code> object isn't garbage collected, the <code>Class</code>-object reference will continue to exist, preventing the class from being unloaded. The created thread is given "daemon" status so that its existence won't stop the program from terminating when the non-daemon threads shut down. <P> <!-- --------- LISTING 2 (/src/com/holub/asynch/JDK_11_unloading_bug_fix.java) --------- --> <a name="_listing2_"> <table border=1 cellspacing=0 cellpadding=10> <caption><strong>Listing 2 (<em>/src/com/holub/asynch/JDK_11_unloading_bug_fix.java</em>): Fixing the 1.1 JDK's unloading problem</strong></caption> <tr> <td valign=top> <!-- file: /src/com/holub/asynch/JDK_11_unloading_bug_fix.java --> <table border=0 cellspacing=0 cellpadding=0><tr><td valign=top align=right><pre> 01 02 </pre></td> <td valign=top> <pre> package com.holub.asynch; </pre> </td></tr> <tr><td></td><td valign=top><pre> /**<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> <table border=1 cellspacing=0 cellpadding=5><tr><td><font size=-1><em> <center>(c) 1999, Allen I. Holub.</center> <p> This code may not be distributed by yourself except in binary form, incorporated into a java .class file. You may use this code freely for personal purposes, but you may not incorporate it into any commercial product without getting my express permission in writing. </td></tr></table> <p> This class provides a workaround for a bug in the JDK 1.1 VM that unloads classes too aggressively. The problem is that if the only reference to an object is held in a static member of the object, the class is subject to unloading, and the static member will be discarded. This behavior causes a lot of grief when you're implementing a Singleton. Use it like this: <P> <pre> class Singleton { private Singleton() { new JDK_11_unloading_bug_fix(Singleton.class); } // ... } </pre> <P> In either event, once the "JDK_11_unloading_bug_fix" object is created, the class (and its static fields) won't be unloaded for the life of the program. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 </pre></td> <td valign=top> <pre> <a name="JDK_11_unloading_bug_fix">public class JDK_11_unloading_bug_fix</a> { <a name="JDK_11_unloading_bug_fix.JDK_11_unloading_bug_fix(Class)"> public JDK_11_unloading_bug_fix( final Class the_class )</a> { if( System.getProperty("java.version").startsWith("1.1") ) { Thread t = new Thread() <a name="JDK_11_unloading_bug_fix.singleton_class"> { private Class singleton_class = the_class;</a> <a name="JDK_11_unloading_bug_fix.run()"> public synchronized void run()</a> { try{ wait(); }catch(InterruptedException e){} } }; t.setDaemon(true); // otherwise the program won't shut down t.start(); } } } </pre> </td></tr> </table> </td> </tr> </table> </a> <!-- --------- END LISTING 2 --------- --> <P> <FONT SIZE="+1"><STRONG>Reader/writer locks</STRONG></FONT><BR> And now for something completely different... <P> Controlling access to a shared resource such as a file or a data structure in a multithreaded environment is a commonplace problem. Typically, you'd like to allow any number of threads to simultaneously read from or otherwise access a resource, but you want only one thread at a time to be able to write to or otherwise modify the resource. That is, <em>read</em> operations can go on in parallel, but <em>write</em> operations must be serialized -- and reads and writes can't go on simultaneously. Moreover, it's nice if the write requests are guaranteed to be processed in the order they are received so that sequential writes to a file, for example, are indeed sequential. <P> The simplest solution to this problem is to lock the entire data structure -- just synchronize everything. But this approach is too simplistic to be workable in the real world. With most resources (such as data structures and file systems), there's absolutely no problem with multiple threads all accessing a shared resource simultaneously, provided the resource isn't modified while it's being accessed. If the "read" operations were all synchronized methods, though, no thread could read while another was in the process of reading: You'd effectively serialize the read operations. <P> This problem is solved using a <em>reader/writer lock</em>. An attempt to acquire the lock for reading will block only if any write operations are in progress, so simultaneous read operations are the norm. An attempt to acquire the lock for writing will block while ether read or write operations are in progress, and the requesting thread will be released when the current read or write completes. Write operations are serialized (on a first-come, first-served basis in the current implementation), so that no two writing threads will be permitted to write simultaneously. Readers who are waiting when a writer thread completes are permitted to execute (in parallel) before subsequent write operations are permitted. <P> <a href="#_listing3_">Listing 3</a> implements a reader/writer lock that behaves as I've just described. Generally, you'll use it like this: <P> <pre> <a name="Data_structure_or_resource">public class Data_structure_or_resource</a> { Reader_writer lock = new Reader_writer(); <a name="Data_structure_or_resource.access()"> public void access( )</a> {<strong> try { lock.request_read();</strong> // do the read/access operation here.<strong> } finally { lock.read_accomplished(); }</strong> } <a name="Data_structure_or_resource.modify()"> public void modify( )</a> {<strong> try { lock.request_write();</strong> // do the write/modify operation here.<strong> } finally { lock.write_accomplished(); }</strong> } } </pre> <P> I've also provided nonblocking versions of <code>request_write()</code> (<code>request_immediate_write()</code>, <a href="#Reader_writer.request_immediate_write()">Listing 3, line 65</a>) and <code>request_read()</code> (<code>request_immediate_read()</code>, <a href="#Reader_writer.request_immediate_read()">Listing 3, line 24</a>), which return error flags (<code>false</code>) if they can't get the resource, but these are not used as often as the blocking forms. <P> The implementation logic is straightforward, and requires a surprisingly small amount of code. (Most of Listing 3 is made up of comments and a test routine.) I keep a count of the number of active readers -- readers that are in the process of reading (<code>active_readers</code> (<a href="#Reader_writer.active_readers">Listing 3, line 8</a>)). This count is incremented when a reader requests the lock, and is decremented when the reader releases the lock. If a writer thread comes along and requests access to the resource while reads are in progress, we have to wait for the active readers to finish before the writer can be let loose. A lock is created (on line <a href="#Reader_writer.java.lock_create">49</a>), and the requesting thread is made to <code>wait()</code> on that lock. These locks are queued up in the <code>writer_locks</code> linked list (<a href="#Reader_writer.writer_locks">Listing 3, line 12</a>). If any additional reader threads come along while a writer is waiting, they are blocked (by a <code>wait()</code> on line <a href="#Reader_writer.java.read_block">20</a>) until the current batch of readers and the waiting writer have finished. (The <code>waiting_readers</code> field [<a href="#Reader_writer.waiting_readers">Listing 3, line 9</a>] keeps track of how many readers are blocked, waiting for access.) Same goes with additional writers that come along at this point; they're just added to the queue of waiting writers, blocked on a roll-your-own lock. <P> As the readers finish up, they call <code>read_accomplished()</code> (<a href="#Reader_writer.read_accomplished()">Listing 3, line 32</a>), which decrements the <code>active_readers</code> count. When that count goes to zero, the first writer in the queue is released. That thread goes off and does its thing, then it calls <code>write_accomplished()</code> (<a href="#Reader_writer.write_accomplished()">Listing 3, line 74</a>). If any readers have been patiently waiting while all this is going on, they're released all at once at this point (they're all waiting on the current <code>Reader_writer</code> object's internal condition variable). When that batch of readers finishes reading, the process just described is repeated, and the next batch of readers is released. If no readers are waiting when a writer completes, then the next writer in line is released. <P> <!-- --------- LISTING 3 (/src/com/holub/asynch/Reader_writer.java) --------- --> <a name="_listing3_"> <table border=1 cellspacing=0 cellpadding=10> <caption><strong>Listing 3 (<em>/src/com/holub/asynch/Reader_writer.java</em>): A reader/writer lock</strong></caption> <tr> <td valign=top> <!-- file: /src/com/holub/asynch/Reader_writer.java --> <table border=0 cellspacing=0 cellpadding=0><tr><td valign=top align=right><pre> 001 002 003 004 </pre></td> <td valign=top> <pre> package com.holub.asynch; import java.util.LinkedList; </pre> </td></tr> <tr><td></td><td valign=top><pre> /**<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> <table border=1 cellspacing=0 cellpadding=5><tr><td><font size=-1><em> <center>(c) 1999, Allen I. Holub.</center> <p> This code may not be distributed except in binary form, incorporated into a java .class file. You may use this code freely for personal purposes, but you may not incorporate it into any commercial product without getting my express permission in writing. </td></tr></table> <p> This reader/writer lock prevents reads from occurring while writes are in progress, and it also prevents multiple writes from happening simultaneously. Multiple read operations can run in parallel, however. Reads take priority over writes, so any read operations that are pending while a write is in progress will execute before any subsequent writes execute. Writes are guaranteed to execute in the order in which they were requested -- the oldest request is processed first. <p> You should use the lock as follows: <pre> public class Data_structure_or_resource { Reader_writer lock = new Reader_writer(); public void access( ) {<strong> try { lock.request_read();</strong> // do the read/access operation here.<strong> } finally { lock.read_accomplished(); }</strong> } public void modify( ) {<strong> try { lock.request_write();</strong> // do the write/modify operation here.<strong> } finally { lock.write_accomplished(); }</strong> } } </pre> <font size=-1> This implementation is based on the one in Doug Lea's <em>Concurrent Programming in Java</em> (Addison Wesley, 1997, pp. 300-303), I've simplified the code (and cleaned it up) and added the nonblocking acquisition methods. I've also made the lock a standalone class rather than a base class from which you have to derive. You might also want to look at the very different implementation of the reader/writer lock in Scott Oaks and Henry Wong's <em>Java Threads</em> (O'Reilly, 1997, pp. 180-187). </font> <br><strong>@author <em>Allen</em></strong> I. Holub </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 005 006 007 008 009 010 011 </pre></td> <td valign=top> <pre> <a name="Reader_writer">public class Reader_writer</a> { <a name="Reader_writer.active_readers"> private int active_readers; // = 0</a> <a name="Reader_writer.waiting_readers"> private int waiting_readers; // = 0</a> <a name="Reader_writer.active_writers"> private int active_writers; // = 0</a> </pre> </td></tr> <tr><td></td><td valign=top><pre> /******************************************************************<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> I keep a linked list of writers waiting for access so that I can release them in the order that the requests were received. The size of this list is the "waiting writers" count. Note that the monitor of the <code>Reader_writer</code> object itself is used to lock out readers while writes are in progress, thus there's no need for a separate "reader_lock." </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 012 013 </pre></td> <td valign=top> <pre> <a name="Reader_writer.writer_locks"> private final LinkedList writer_locks = new LinkedList();</a> </pre> </td></tr> <tr><td></td><td valign=top><pre> /******************************************************************<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> Request the read lock. Block until a read operation can be performed safely. This call must be followed by a call to <code>read_accomplished()</code> when the read operation completes. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 014 015 016 017 018 019 020 021 022 023 </pre></td> <td valign=top> <pre> <a name="Reader_writer.request_read()"> public synchronized void request_read()</a> { if( active_writers==0 && writer_locks.size()==0 ) ++active_readers; else { ++waiting_readers; <a name="Reader_writer.java.read_block"> try{ wait(); }catch(InterruptedException e){}</a> } } </pre> </td></tr> <tr><td></td><td valign=top><pre> /******************************************************************<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> This version of <code>read()</code> requests read access and returns <em>true</em> if you get it. If it returns <em>false,</em> you may not safely read from the guarded resource. If it returns <em>true,</em> you should do the read, then call <code>read_accomplished</code> in the normal way. Here's an example: <pre> public void read() { if( lock.request_immediate_read() ) { try { // do the read operation here } finally { lock.read_accomplished(); } } else // couldn't read safely. } </pre> </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 024 025 026 027 028 029 030 031 </pre></td> <td valign=top> <pre> <a name="Reader_writer.request_immediate_read()"> public synchronized boolean request_immediate_read()</a> { if( active_writers==0 && writer_locks.size()==0 ) { ++active_readers; return true; } return false; } </pre> </td></tr> <tr><td></td><td valign=top><pre> /******************************************************************<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> Release the lock. You must call this method when you're done with the read operation. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 032 033 034 035 </pre></td> <td valign=top> <pre> <a name="Reader_writer.read_accomplished()"> public synchronized void read_accomplished()</a> { if( --active_readers == 0 ) notify_writers(); } </pre> </td></tr> <tr><td></td><td valign=top><pre> /******************************************************************<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> Request the write lock. Block until a write operation can be performed safely. Write requests are guaranteed to be executed in the order received. Pending read requests take precedence over all write requests. This call must be followed by a call to <code>write_accomplished()</code> when the write operation completes. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 </pre></td> <td valign=top> <pre> <a name="Reader_writer.request_write()"> public void request_write()</a> { // This method can't be synchronized or there'd be a nested-monitor // lockout problem: We have to acquire the lock for "this" in // order to modify the fields, but that lock must be released // before we start waiting for a safe time to do the writing. // If request_write() were synchronized, we'd be holding // the monitor on the Reader_writer lock object while we were // waiting. Since the only way to be released from the wait is // for someone to call either read_accomplished() // or write_accomplished() (both of which are synchronized), // there would be no way for the wait to terminate. <a name="Reader_writer.java.lock_create"> Object lock = new Object();</a> synchronized( lock ) { synchronized( this ) { boolean okay_to_write = writer_locks.size()==0 && active_readers==0 && active_writers==0; if( okay_to_write ) { ++active_writers; return; // the "return" jumps over the "wait" call } writer_locks.addLast( lock ); } try{ lock.wait(); } catch(InterruptedException e){} } } </pre> </td></tr> <tr><td></td><td valign=top><pre> /******************************************************************<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> This version of the write request returns <em>false</em> immediately (without blocking) if any read or write operations are in progress and a write isn't safe; otherwise, it returns <em>true</em> and acquires the resource. Use it like this: <pre> public void write() { if( lock.request_immediate_write() ) { try { // do the write operation here } finally { lock.write_accomplished(); } } else // couldn't write safely. } </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 065 066 067 068 069 070 071 072 073 </pre></td> <td valign=top> <pre> <a name="Reader_writer.request_immediate_write()"> synchronized public boolean request_immediate_write()</a> { if( writer_locks.size()==0 && active_readers==0 && active_writers==0 ) { ++active_writers; return true; } return false; } </pre> </td></tr> <tr><td></td><td valign=top><pre> /******************************************************************<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> Release the lock. You must call this method when you're done with the read operation. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 </pre></td> <td valign=top> <pre> <a name="Reader_writer.write_accomplished()"> public synchronized void write_accomplished()</a> { // The logic here is more complicated than it appears. // If readers have priority, you'll notify them. As they // finish up, they'll call read_accomplished(), one at // a time. When they're all done, read_accomplished() will // notify the next writer. If no readers are waiting, then // just notify the writer directly. --active_writers; if( waiting_readers > 0 ) // priority to waiting readers notify_readers(); else notify_writers(); } </pre> </td></tr> <tr><td></td><td valign=top><pre> /******************************************************************<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> Notify all the threads that have been waiting to read. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 089 090 091 092 093 094 </pre></td> <td valigngn=top> <pre> <a name="Reader_writer.notify_readers()"> private void notify_readers() // must be accessed from a</a> { // synchronized method active_readers += waiting_readers; waiting_readers = 0; notifyAll(); } </pre> </td></tr> <tr><td></td><td valign=top><pre> /******************************************************************<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> Notify the writing thread that has been waiting the longest. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 095 096 097 098 099 100 101 102 103 104 </pre></td> <td valign=top> <pre> <a name="Reader_writer.notify_writers()"> private void notify_writers() // must be accessed from a</a> { // synchronized method if( writer_locks.size() > 0 ) { Object oldest = writer_locks.removeFirst(); ++active_writers; synchronized( oldest ){ oldest.notify(); } } } </pre> </td></tr> <tr><td></td><td valign=top><pre> /*******************************************************************<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> The <code>Test</code> class is a unit test for the other code in the current file. Run the test with: <pre> java com.holub.asynch.Reader_writer\$Test </pre> (the backslash isn't required with windows boxes), and don't include this class file in your final distribution. The output could vary in trivial ways, depending on system timing. The read/write order should be exactly the same as in the following sample: <pre> Starting w/0 w/0 writing Starting r/1 Starting w/1 Starting w/2 Starting r/2 Starting r/3 w/0 done Stopping w/0 r/1 reading r/2 reading r/3 reading r/1 done Stopping r/1 r/2 done r/3 done Stopping r/2 Stopping r/3 w/1 writing w/1 done Stopping w/1 w/2 writing w/2 done Stopping w/2 </pre> </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 105 106 107 108 </pre></td> <td valign=top> <pre> <a name="Reader_writer.Test"> public static class Test</a> { Resource resource = new Resource(); </pre> </td></tr> <tr><td></td><td valign=top><pre> /**<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> The <code>Resource</code> class simulates a simple locked resource. The read operation simply pauses for .1 seconds. The write operation (which is typically higher overhead) pauses for .5 seconds. Note that the use of <code>try...finally</code> is not critical in the current test, but it's good style to always release the lock in a <code>finally</code> block in real code. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 </pre></td> <td valign=top> <pre> <a name="Reader_writer.Test.Resource"> static class Resource</a> { Reader_writer lock = new Reader_writer(); <a name="Reader_writer.Test.Resource.read(String)"> public void read( String reader )</a> { try { lock.request_read(); System.out.println( "\t\t" + reader + " reading" ); try{ Thread.currentThread().sleep( 100 ); } catch(InterruptedException e){} System.out.println( "\t\t" + reader + " done" ); } finally { lock.read_accomplished(); } } <a name="Reader_writer.Test.Resource.write(String)"> public void write( String writer )</a> { try { lock.request_write(); System.out.println( "\t\t" + writer + " writing" ); try{ Thread.currentThread().sleep( 500 ); } catch(InterruptedException e){} System.out.println( "\t\t" + writer + " done" ); } finally { lock.write_accomplished(); } } <a name="Reader_writer.Test.Resource.read_if_possible()"> public boolean read_if_possible()</a> { if( lock.request_immediate_read() ) { // in the real world, you'd actually do the read here lock.read_accomplished(); return true; } return false; } <a name="Reader_writer.Test.Resource.write_if_possible()"> public boolean write_if_possible()</a> { if( lock.request_immediate_write() ) { // in the real world, you'd actually do the write here lock.write_accomplished(); return true; } return false; } } </pre> </td></tr> <tr><td></td><td valign=top><pre> /**<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> A simple reader thread. Just reads from the resource, passing it a unique string id. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 158 159 160 161 162 163 164 165 166 167 </pre></td> <td valign=top> <pre> <a name="Reader_writer.Test.Reader"> class Reader extends Thread</a> <a name="Reader_writer.Test.Reader.name"> { private String name;</a> Reader( String name ){ this.name = name; } <a name="Reader_writer.Test.Reader.run()"> public void run( )</a> { System.out.println("Starting " + name ); resource.read( name ); System.out.println("Stopping " + name ); } } </pre> </td></tr> <tr><td></td><td valign=top><pre> /**<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> A simple writer thread. Just writes to the resource, passing it a unique string id. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 168 169 170 171 172 173 174 175 176 177 178 </pre></td> <td valign=top> <pre> <a name="Reader_writer.Test.Writer"> class Writer extends Thread</a> <a name="Reader_writer.Test.Writer.name"> { private String name;</a> Writer( String name ){ this.name = name; } <a name="Reader_writer.Test.Writer.run()"> public void run()</a> { System.out.println("Starting " + name ); resource.write( name ); System.out.println("Stopping " + name ); } } </pre> </td></tr> <tr><td></td><td valign=top><pre> /**<table border=0 cellpadding=0 cellspacing=0><tr><td valign=top><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code><code> </code></td><td valign=top bgcolor=#999999><font color=#999999>|</font></td><td> </td><td valign=top><font size=-1> Test by creating several readers and writers. The initial write operation (w/0) should complete before the first read (r/1) runs. Since readers have priority, r/2 and r/3 should run before w/1; and r/1, r/2 and r3 should all run in parallel. When all three reads complete, w1 and w2 should execute sequentially in that order. </font></td></tr></table> */ </pre> </td></tr> <tr><td valign=top align=right><pre> 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 </pre></td> <td valign=top> <pre> <a name="Reader_writer.Test.Test()"> public Test()</a> { if( !resource.read_if_possible() ) System.out.println("Immediate read request didn't work"); if( !resource.write_if_possible() ) System.out.println("Immediate write request didn't work"); new Writer( "w/0" ).start(); new Reader( "r/1" ).start(); new Writer( "w/1" ).start(); new Writer( "w/2" ).start(); new Reader( "r/2" ).start(); new Reader( "r/3" ).start(); } <a name="Reader_writer.Test.main(String[])"> static public void main( String[] args )</a> { Test t = new Test(); } } } </pre> </td></tr> </table> </td> </tr> </table> </a> <!-- --------- END LISTING 3 --------- --> <P> <FONT SIZE="+1"><STRONG>It's a wrap</STRONG></FONT><BR> So, that's it for the part of this series that discusses what I think of as the "low-level" thread-related problems. The toolkit I've developed over the past few months should put you well on the way to solving many thorny issues that crop up in every multithreaded program. But we're not done yet. <P> If you've been following this series from the beginning, you're probably asking yourself why you ever thought that programming with threads was a good idea. There's just so much complexity, and the bugs are so hard to find. Fortunately, there is a general solution to both problems: good architecture. It's possible to design a program for multithreading in such a way that many of the synchronization issues I've been discussing become immaterial. (Which is not to say that synchronization-related problems don't pop up regularly, even when the overall system is well designed. I regularly use all those semaphores and locks we've been looking at for the last few months. With the proper architecture, though, synchronization issues do tend to move to the background). Next month I'll start looking at architectural solutions to threading problems, with a discussion of thread pools and synchronous dispatching. <IMG HEIGHT="8" WIDTH="8" SRC="/javaworld/icons/dingbat.gif"> <P> <!-- end body text --> <P> <CENTER><FORM METHOD="POST" ACTION="/javaworld/cgi-bin/jw-nav.cgi"> <SELECT NAME="jump_list"> <option value="http://www.javaworld.com/javaworld/jw-04-1999/index.html"> Also this month in JavaWorld <option value="http://www.javaworld.com/javaworld/jw-04-1999/index.html#nuts"> Nuts & Bolts: <OPTION VALUE="http://www.javaworld.com/javaworld/jw-04-1999/jw-04-step.html"> - Reading textual data: Fun with streams <OPTION VALUE="http://www.javaworld.com/javaworld/jw-04-1999/jw-04-techniques.html"> - Farewell to Design Techniques <OPTION VALUE="http://www.javaworld.com/javaworld/jw-04-1999/jw-04-cooltools.html"> - Easily reconfigure your applications while they run <OPTION VALUE="http://www.javaworld.com/javaworld/jw-04-1999/jw-04-middleware.html"> - The State Of Java Middleware, Part II: Enterprise JavaBeans <OPTION VALUE="http://www.javaworld.com/javaworld/jw-04-1999/jw-04-xml.html"> - XML for the absolute beginner <OPTION VALUE="http://www.javaworld.com/javaworld/jw-04-1999/jw-04-enterprise.html"> - Write high performance RMI servers and Swing clients <OPTION VALUE="http://www.javaworld.com/javaworld/javatips/jw-javatip71.html"> - Java Tip 71: Use dynamic messaging in Java <option value="http://www.javaworld.com/javaworld/jw-04-1999/index.html#news"> News & Views: <OPTION VALUE="http://www.javaworld.com/javaworld/jw-04-1999/jw-04-newsbriefs.html"> - News and New Product Briefs (3/20/99) <OPTION VALUE="http://www.javaworld.com/javaworld/jw-04-1999/jw-04-idgns-jini.html"> - Sun and Nippon company team up on Java and Jini <OPTION VALUE="http://www.javaworld.com/javaworld/jw-04-1999/jw-04-idgns-xml.html"> - Sun extends Java to support XML <OPTION VALUE="http://www.javaworld.com/javaworld/jw-04-1999/jw-04-iw-informsyb.html"> - Informix and Sybase bring Java to databases <OPTION VALUE="http://www.javaworld.com/javaworld/jw-04-1999/jw-04-letters1.html"> - Letters to the Editor (3/20/99) <OPTION VALUE="http://www.javaworld.com/javaworld/jw-04-1999/jw-04-sunsource.html"> - Sun keeps its foot in Java's door <OPTION VALUE="http://www.javaworld.com/javaworld/jw-04-1999/jw-04-newsbriefs2.html"> - News and New Product Briefs (4/05/99) </SELECT> <INPUT TYPE="SUBMIT" VALUE="Go"> </FORM></CENTER> <CENTER><TABLE CELLPADDING="0" BORDER="0"><TR><TD> <NOLAYER> <IFRAME SRC="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=468x60" width=468 height=60 marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=no ><A HREF="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=468x60"><IMG SRC="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=468x60" width=468 height=60></A></IFRAME> </NOLAYER> <ilayer id=ph4 visibility=hide align=center width=468 height=60></ilayer> </TD></TR></TABLE></CENTER> <BR> <CENTER><TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR><TD> <NOLAYER> <IFRAME SRC="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=125x125;tile=1" height=125 width=125 marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=no><A HREF="http://ad.doubleclick.net/jump/idg.jw.com/archives;sz=125x125;tile=1"><IMG SRC="http://ad.doubleclick.net/ad/idg.jw.com/archives;sz=125x125;tile=1" height=125 width=125></A></IFRAME> </NOLAYER> <ilayer id=ph5 visibility=hide height=125 width=125></ilayer> </TD> <TD> </TD> <TD> <NOLAYER> <IFRAME SRC="http://ad.doubleclick.net/adi/idg.jw.com/archives;sz=125x125;tile=2" height=125 width=125 marginwidth=0 marginheight=0 hspace=0 vspace=0 frameborder=0 scrolling=no><A HREF="http://ad.doubleclick.net/jump/idg.jw.com/archives;sz=125x125;tile=2"><IMG SRC="http://ad.doubleclick.net/ad/idg.jw.com/archives;sz=125x125;tile=2" height=125 width=125></A></IFRAME> </NOLAYER> <ilayer id=ph6 visibility=hide height=125 width=125></ilayer> </TD></TR></TABLE></CENTER> <P> <P> <CENTER><IMG WIDTH="468" HEIGHT="4" SRC="/javaworld/icons/green.gif"></CENTER> <P> <A NAME="resources"><STRONG>Resources</STRONG></A> <UL> <LI>Bill Venners discussed static members, though without much coverage of the implementation issues, in his <strong>Design Techniques</strong> column, "Design with static members"<BR> <A HREF="http://www.javaworld.com/javaworld/jw-03-1999/jw-03-techniques.html">http://www.javaworld.com/javaworld/jw-03-1999/jw-03-techniques.html</a> <LI>The Singleton pattern is presented in the <strong>"Gang of Four"</strong> (or GoF) book: Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides's <em>Design Patterns: Elements of Reusable Object-Oriented Software</em> (Reading, MA: Addison Wesley, 1995). This book is essential reading for any OO designer.<BR> <A HREF=""></a> <LI>John Vlissides's <em>Pattern Hatching: Design Patterns Applied</em> (Reading, MA: Addison Wesley, 1998) also has a lot to say about Singletons in Chapter 2 and the first section of Chapter 3.<BR> <A HREF=""></a> <LI>The double-checked locking strategy for Singleton creation is described in "Double-Checked Locking" by Douglas C. Schmidt and Tim Harrison, <em>Pattern Languages of Program Design 3</em> (Reading, MA: Addison Wesley, 1998, pp. 363-375).<BR> <A HREF=""></a> <LI>Reader/writer locks are described in Doug Lea's <em>Concurrent Programming in Java</em> (Reading, MA: Addison Wesley, 1997, pp. 300-303). My implementation is based on Lea's.<BR> <A HREF=""></a> <LI>Reader/writer locks are also described in Scott Oaks and Henry Wong's <em>Java Threads</em> (Sebastopol, CA: O'Reilly, 1997, pp. 180-187).<BR> <A HREF=""></a> </UL> <CENTER><IMG WIDTH="468" HEIGHT="4" SRC="/javaworld/icons/green.gif"></CENTER> <P> <STRONG>About the author</STRONG><BR> Allen Holub has been working in the computer industry since 1979. He is widely published in magazines (<em>Dr. Dobb's Journal,</em> <em>Programmers Journal</em>, <em>Byte</em>, <em>MSJ</em>, among others). He has seven books to his credit, and is currently working on an eighth that will present the complete sources for a Java compiler written in Java. After eight years as a C++ programmer, Allen abandoned C++ for Java in early 1996. He now looks at C++ as a bad dream, the memory of which is mercifully fading. He's been teaching programming (first C, then C++ and MFC, now OO-Design and Java) both on his own and for the University of California Berkeley Extension since 1982. Allen offers both public classes and in-house training in Java and object-oriented design topics. He also does object-oriented design consulting and contract Java programming. Get information, and contact Allen, via his Web site <a href="http://www.holub.com">http://www.holub.com</a>. Reach Allen at <A NAME="author" HREF="/javaworld/cgi-bin/jw-mailto.cgi?allen.holub@javaworld.com+/javaworld/jw-04-1999/jw-04-toolbox.html+author">allen.holub@javaworld.com</a>. <BR CLEAR="ALL") <P> <FORM METHOD="POST" ACTION="/javaworld/cgi-bin/jw-mini-survey.cgi?1999-jw-04-toolbox.html"> <a name="mini-ditka"> <strong>What did you think of this article?</strong><br> </a> <table width="100%" cellpadding="0" border="0"> <tr> <td align="left" valign="top" rowspan="1" colspan="1"> <INPUT TYPE="radio" NAME="worth" VALUE="3">-Very worth reading<br> <INPUT TYPE="radio" NAME="worth" VALUE="2">-Worth reading<br> <INPUT TYPE="radio" NAME="worth" VALUE="1">-Not worth reading<br> </td> <td align="left" valign="top" rowspan="1" colspan="1"> <INPUT TYPE="radio" NAME="length" VALUE="3">-Too long<br> <INPUT TYPE="radio" NAME="length" VALUE="2">-Just right<br> <INPUT TYPE="radio" NAME="length" VALUE="1">-Too short<br> </td> <td align="left" valign="top" rowspan="1" colspan="1"> <INPUT TYPE="radio" NAME="tech" VALUE="3">-Too technical<br> <INPUT TYPE="radio" NAME="tech" VALUE="2">-Just right<br> <INPUT TYPE="radio" NAME="tech" VALUE="1">-Not technical enough<br> </td> </tr> </table> <table cellpadding="0" border="0"> <tr> <td align="left" valign="top" rowspan="1" colspan="1"> <TEXTAREA NAME="comments" COLS="40" ROWS="3">Comments: </TEXTAREA> </td> </tr> <tr> <td align="left" valign="top" rowspan="1" colspan="2"> <TEXTAREA NAME="comments" COLS="30" ROWS="1" WRAP="VIRTUAL">Name: </TEXTAREA> </td> </tr> <tr> <td align="left" valign="top" rowspan="1" colspan="2"> <TEXTAREA NAME="comments" COLS="30" ROWS="1" WRAP="VIRTUAL">Email: </TEXTAREA> </td> </tr> <tr> <td align="left" valign="top" rowspan="1" colspan="1"> <TEXTAREA NAME="comments" COLS="30" ROWS="1" WRAP="VIRTUAL">Company Name: </TEXTAREA> </td> <td align="left" valign="bottom"> <INPUT TYPE="submit" VALUE="Send data"> </td> </tr> </table> </FORM> <P> <center> <a href="/javaworld/jw-04-1999/index.html"><img border="0" width="74" height="21" src="/javaworld/icons/b-home.gif" alt="[JavaWorld Main Page]"></a> <a href="/javaworld/search.html"><img border="0" width="107" height="21" src="/javaworld/icons/b-search.gif" alt="[JavaWorld Search]"></a> <a href="/javaworld/jw-04-1999/index.html#nuts"><img border="0" width="107" height="21" src="/javaworld/icons/b-nuts2.gif" alt="[Nuts & Bolts]"></a> <a href="/javaworld/jw-04-1999/index.html#news"><img border="0" width="107" height="21" src="/javaworld/icons/b-news.gif" alt="[News & Views]"></a> <a href="/javaworld/jw-04-1999/index.html#res"><img border="0" width="107" height="21" src="/javaworld/icons/b-jr.gif" alt="[Java Resources]"></a> </center> <P> <CENTER><A HREF="/javaworld/common/jw-copyright99.html"><IMG BORDER="0" width="338" height="20" SRC="/javaworld/icons/b-copyright99.gif" ALT="[(c) Copyright 1999 Web Publishing Inc., an IDG Communications company]"></A></CENTER> <P> If you have problems with this magazine, contact <A NAME="webmaster" HREF="/javaworld/cgi-bin/jw-mailto.cgi?webmaster@javaworld.com+/javaworld/jw-04-1999/jw-04-toolbox.html+webmaster">webmaster@javaworld.com</A> <BR> URL: http://www.javaworld.com/javaworld/jw-04-1999/jw-04-toolbox.html <BR> Last modified: Friday, March 26, 1999 <!-- BEGIN DART BANNERS (NETSCAPE LAYERS) --> <layer src="http://ad.doubleclick.net/adl/idg.jw.com/archives;sz=468x60" visibility=hide onload="moveToAbsolute(ph1.pageX, ph1.pageY); visibility='show';"></layer> <layer src="http://ad.doubleclick.net/adl/idg.jw.com/archives;sz=125x125;tile=1" visibility=hide onload="moveToAbsolute(ph2.pageX, ph2.pageY);visibility='show';"></layer> <layer src="http://ad.doubleclick.net/adl/idg.jw.com/archives;sz=125x125;tile=2" visibility=hide onload="moveToAbsolute(ph3.pageX, ph3.pageY);visibility='show';"></layer> <layer src="http://ad.doubleclick.net/adl/idg.jw.com/archives;sz=468x60" visibility=hide onload="moveToAbsolute(ph4.pageX, ph4.pageY); visibility='show';"></layer> <layer src="http://ad.doubleclick.net/adl/idg.jw.com/archives;sz=125x125;tile=1" visibility=hide onload="moveToAbsolute(ph5.pageX, ph5.pageY);visibility='show';"></layer> <layer src="http://ad.doubleclick.net/adl/idg.jw.com/archives;sz=125x125;tile=2" visibility=hide onload="moveToAbsolute(ph6.pageX, ph6.pageY);visibility='show';"></layer> <!-- END DART BANNERS (NETSCAPE LAYERS) --></BODY> </HTML> --------------E0FCE998436E2BE7ED79C45D--