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