1  // File: SharedCell.java (Fig. 13.6 in JHTP2)
  2  //
  3  // Show multiple threads modifying shared object.
  4  // Use synchronization to ensure that both threads 
  5  // access the shared cell properly.
  6  
  7  import java.applet.Applet;
  8  import java.awt.*;
  9  import java.text.DecimalFormat;
 10  
 11  public class SharedCell extends Applet {
 12     private TextArea output;
 13  
 14     public void init()
 15     {
 16        setLayout( new BorderLayout() );
 17        output = new TextArea();
 18        add( output, BorderLayout.CENTER );
 19     }
 20  
 21     public void start()
 22     {
 23        HoldInteger h = new HoldInteger( output );
 24        ProduceInteger p = new ProduceInteger( h );
 25        ConsumeInteger c = new ConsumeInteger( h );
 26  
 27        p.start();
 28        c.start();
 29     }
 30  }
 31  
 32  class ProduceInteger extends Thread {
 33     private HoldInteger pHold;
 34  
 35     public ProduceInteger( HoldInteger h )
 36     {
 37        pHold = h;
 38     }
 39  
 40     public void run()
 41     {
 42        for ( int count = 0; count < 10; count++ ) {
 43           // sleep for a random interval
 44           try {
 45              Thread.sleep( (int) ( Math.random() * 500 ) );
 46           }
 47           catch( InterruptedException e ) {
 48              System.err.println( e.toString() );
 49           }
 50  
 51           pHold.setSharedInt( count );
 52           System.out.println( "Produced set sharedInt to " +
 53                               count );
 54        }
 55  
 56        pHold.setMoreData( false );
 57     }
 58  }
 59  
 60  class ConsumeInteger extends Thread {
 61     private HoldInteger cHold;
 62  
 63     public ConsumeInteger( HoldInteger h )
 64     {
 65        cHold = h;
 66     }
 67  
 68     public void run()
 69     {
 70        int val;
 71  
 72        while ( cHold.hasMoreData() ) {
 73           // sleep for a random interval
 74           try {
 75              Thread.sleep( (int) ( Math.random() * 3000 ) );
 76           }
 77           catch( InterruptedException e ) {
 78              System.err.println( e.toString() );
 79           }
 80  
 81           val = cHold.getSharedInt();
 82           System.out.println( "Consumer retrieved " + val );
 83        } 
 84     }
 85  }
 86  
 87  class HoldInteger {
 88     private int sharedInt[] = { -1, -1, -1, -1, -1 };
 89     private boolean moreData = true;
 90     private boolean writeable = true;
 91     private boolean readable = false;
 92     private int readLoc = 0, writeLoc = 0;
 93     private TextArea output;
 94  
 95     public HoldInteger( TextArea out )
 96     {
 97        output = out;
 98     }
 99  
100     public synchronized void setSharedInt( int val )
101     {
102        while ( !writeable ) {
103           try {
104              output.append( " WAITING TO PRODUCE " + val );
105              wait();
106           }
107           catch ( InterruptedException e ) {
108              System.err.println( e.toString() );
109           }
110        }
111  
112        sharedInt[ writeLoc ] = val;
113        readable = true;
114  
115        output.append( "\nProduced " + val +
116                           " into cell " + writeLoc );
117  
118        writeLoc = ( writeLoc + 1 ) % 5;
119  
120        output.append( "\twrite " + writeLoc +
121                       "\tread " + readLoc );
122        printBuffer( output, sharedInt );
123  
124        if ( writeLoc == readLoc ) {
125           writeable = false;
126           output.append( "\nBUFFER FULL" );
127        }
128  
129        notify();
130     }
131  
132     public synchronized int getSharedInt()
133     {
134        int val;
135  
136        while ( !readable ) {
137           try {
138              output.append( " WAITING TO CONSUME" );
139              wait();
140           }
141           catch ( InterruptedException e ) {
142              System.err.println( e.toString() );
143           }
144        }
145  
146        writeable = true;
147        val = sharedInt[ readLoc ];
148  
149        output.append( "\nConsumed " + val +
150                           " from cell " + readLoc );
151  
152        readLoc = ( readLoc + 1 ) % 5;
153  
154        output.append( "\twrite " + writeLoc +
155                       "\tread " + readLoc );
156        printBuffer( output, sharedInt );
157  
158        if ( readLoc == writeLoc ) {
159           readable = false;
160           output.append( "\nBUFFER EMPTY" );
161        }
162  
163        notify();
164        return val;
165     }
166  
167     public void printBuffer( TextArea out, int buf[] )
168     {
169        DecimalFormat threeChars = new DecimalFormat( " #;-#" );
170        output.append( "\tbuffer: " );
171  
172        for ( int i = 0; i < buf.length; i++ )
173           out.append( " " + threeChars.format( buf[ i ] ) );
174     }
175  
176     public void setMoreData( boolean b ) { moreData = b; }
177  
178     public boolean hasMoreData()
179     {
180        if ( moreData == false && readLoc == writeLoc )
181           return false;
182        else
183           return true;
184     }
185  }
186  
187