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 4

Condition variables and counting semaphores -- filling in a few chinks in Java's threading model

  • Print
  • Feedback

Page 6 of 7

There are still a few problems that have to be fixed to make this all work in the real world. For example, there's no way for a program to know if the user overtypes a string when nobody fetches the original string before it's overwritten. Input strings should be queued up as they come in and read_line() should return a string from the queue if there is one, blocking only if the queue is empty. Listing 3 serves to illustrate the problem at hand without addressing these other issues.

Listing 3: Using a Condition object
01 | import java.awt.*;
02 | import java.awt.event.*;
03 | import com.holub.asynch.Condition;
04 | 
05 | public class Input_source_fixed extends Frame
06 | {
07 |     Condition   text_has_been_entered = new Condition(false); // Initial condition is false
08 | 
09 |     TextField input = new TextField();
10 | 
11 |     public Input_source_fixed()
12 |     {
13 |         input.addActionListener
14 |         (   new ActionListener()
15 |             {   public void actionPerformed( ActionEvent e )
16 |                 {   text_has_been_entered.set_true();  // set the condition true
17 |                 }
18 |             }
19 |         );
20 | 
21 |         add(input);
22 |         pack();
23 |         show();
24 |     }
25 | 
26 |     /** A blocking function that works like readLine(), but gets its
27 |      *  text from the current window's text area. The function doesn't
28 |      *  return until somebody types a line of text, whereupon it returns
29 |      *  the line. Returns null if the user types an empty line.
30 |      */
31 | 
32 |     synchronized String read_line() throws InterruptedException
33 |     {
34 |         text_has_been_entered.wait_for_true();
35 |         text_has_been_entered.set_false();
36 | 
37 |         String entered = input.getText();
38 |         input.setText("");
39 |         return (entered.length() == 0) ? null : entered;
40 | 
41 |     }
42 | 
43 | 
44 |     static public void main( String[] args ) throws Exception
45 |     {   Input_source_fixed source = new Input_source_fixed();
46 |         String input;
47 | 
48 |         while( (input = source.read_line()) != null )
49 |             System.out.println("Got: " + input );
50 | 
51 |         System.exit(0);         // kill the AWT Thread on exit
52 |     }
53 | }


Counting semaphores

The other semaphore I want to look at this month is the "Djikstra" counting semaphore. This one has no direct analog in Java, so it's among the more useful of the com.holub.asynch classes.

Counting semaphores are used to keep track of the availability of a resource within a pool of limited size. For example, you might have four connections open to a database server that are simply recycled to perform multiple queries. This way, you won't incur the overhead of opening a connection every time you make a query. Threads seeking to make queries should block (should be suspended, waiting), if no connections are available. They should be reactivated (released from wait) when a connection becomes available. A counting semaphore can solve this problem (though other solutions -- such as a thread-safe stack with a pop method that blocks if the stack is empty -- are also possible).

Counting semaphores are initialized with a count -- typically the number of objects available in the pool. Every time you acquire the semaphore, the count is decremented; every time you release the semaphore, it's incremented. On acquisition, if the count (after the decrement) is non-0, nothing happens, and you get your slot in the pool. If the count is 0, however, the acquiring thread blocks until some other thread releases the semaphore, thereby incrementing the count.

  • Print
  • Feedback

Resources
  • All the real code discussed in this article (the stuff in the com.holub.asynch package) is available in the "Goodies" section on my Web site. The version on the Web site should be considered the definitive version -- at least it corrects any bugs I know about. http://www.holub.com