Upload
lucas-benson
View
240
Download
0
Embed Size (px)
Citation preview
Java threads
Threaded class extends threadSynchronized class is a monitor
Runnable interface gives thread methodsAll code is
(C) Copyright 1999 by Deitel & Associates, Inc. and Prentice Hall.
ThreadTester.java// Fig. 15.3: ThreadTester.java// Show multiple threads printing at different intervals.
public class ThreadTester { public static void main( String args[] ) { PrintThread thread1, thread2, thread3, thread4;
thread1 = new PrintThread( "thread1" ); thread2 = new PrintThread( "thread2" ); thread3 = new PrintThread( "thread3" ); thread4 = new PrintThread( "thread4" );
System.err.println( "\nStarting threads" );
thread1.start(); thread2.start(); thread3.start(); thread4.start();
System.err.println( "Threads started\n" ); }}
class PrintThread extends Thread
class PrintThread extends Thread { private int sleepTime;
// PrintThread constructor assigns name to thread // by calling Thread constructor public PrintThread( String name ) { super( name );
// sleep between 0 and 5 seconds sleepTime = (int) ( Math.random() * 5000 );
System.err.println( "Name: " + getName() + "; sleep: " + sleepTime ); }
execute the thread
// execute the thread public void run() { // put thread to sleep for a random interval try { System.err.println( getName() + " going to sleep" ); Thread.sleep( sleepTime ); } catch ( InterruptedException exception ) { System.err.println( exception.toString() ); }
// print thread name System.err.println( getName() + " done sleeping" ); }}
ConsumeInteger.java
// Fig. 15.4: ConsumeInteger.java// Definition of threaded class ConsumeIntegerpublic class ConsumeInteger extends Thread { private HoldIntegerUnsynchronized cHold;
public ConsumeInteger( HoldIntegerUnsynchronized h ) { super( "ConsumeInteger" ); cHold = h; }
The run() method
public void run() { int val, sum = 0;
do { // sleep for a random interval try { Thread.sleep( (int) ( Math.random() * 3000 ) ); } catch( InterruptedException e ) { System.err.println( e.toString() ); }
val = cHold.getSharedInt(); sum += val; } while ( val != 10 );
System.err.println( getName() + " retrieved values totaling: " + sum + "\nTerminating " + getName() ); }}
Definition of threaded class ProduceInteger
// Fig. 15.4: ProduceInteger.java// Definition of threaded class ProduceIntegerpublic class ProduceInteger extends Thread { private HoldIntegerUnsynchronized pHold;
public ProduceInteger( HoldIntegerUnsynchronized h ) { super( "ProduceInteger" ); pHold = h; }
The run() method again
public void run() { for ( int count = 1; count <= 10; count++ ) { // sleep for a random interval try { Thread.sleep( (int) ( Math.random() * 3000 ) ); } catch( InterruptedException e ) { System.err.println( e.toString() ); }
pHold.setSharedInt( count ); }
System.err.println( getName() + " finished producing values" + "\nTerminating " + getName() ); }}
Multiple threads modifying shared object
// Fig. 15.4: SharedCell.java// Show multiple threads modifying shared object.public class SharedCell { public static void main( String args[] ) { HoldIntegerUnsynchronized h = new HoldIntegerUnsynchronized(); ProduceInteger p = new ProduceInteger( h ); ConsumeInteger c = new ConsumeInteger( h );
p.start(); c.start(); }}
Definition of threaded class ConsumeInteger
// Fig. 15.5: ConsumeInteger.java// Definition of threaded class ConsumeIntegerpublic class ConsumeInteger extends Thread { private HoldIntegerSynchronized cHold;
public ConsumeInteger( HoldIntegerSynchronized h ) { super( "ConsumeInteger" ); cHold = h; }
Another run() method
public void run() { int val, sum = 0;
do { // sleep for a random interval try { Thread.sleep( (int) ( Math.random() * 3000 ) ); } catch( InterruptedException e ) { System.err.println( e.toString() ); }
val = cHold.getSharedInt(); sum += val; } while ( val != 10 );
System.err.println( getName() + " retrieved values totaling: " + sum + "\nTerminating " + getName() ); }}
Definition of class HoldIntegerSynchronized
// Fig. 15.5: HoldIntegerSynchronized.java// Definition of class HoldIntegerSynchronized that uses thread synchronization to ensure that both// threads access sharedInt at the proper times.public class HoldIntegerSynchronized { private int sharedInt = -1; private boolean writeable = true; // condition variable public synchronized void setSharedInt( int val ) { while ( !writeable ) { // not the producer's turn try { wait(); } catch ( InterruptedException e ) { e.printStackTrace(); } } System.err.println( Thread.currentThread().getName() + " setting sharedInt to " + val ); sharedInt = val;
writeable = false; notify(); // tell a waiting thread to become ready }
public synchronized int getSharedInt() { while ( writeable ) { // not the consumer's turn try { wait(); } catch ( InterruptedException e ) { e.printStackTrace(); } }
writeable = true; notify(); // tell a waiting thread to become ready
System.err.println( Thread.currentThread().getName() + " retrieving sharedInt value " + sharedInt ); return sharedInt; }}
Definition of threaded class ProduceInteger
// Fig. 15.5: ProduceInteger.java// Definition of threaded class ProduceIntegerpublic class ProduceInteger extends Thread { private HoldIntegerSynchronized pHold;
public ProduceInteger( HoldIntegerSynchronized h ) { super( "ProduceInteger" ); pHold = h; }
public void run() { for ( int count = 1; count <= 10; count++ ) { // sleep for a random interval try { Thread.sleep( (int) ( Math.random() * 3000 ) ); } catch( InterruptedException e ) { System.err.println( e.toString() ); }
pHold.setSharedInt( count ); }
System.err.println( getName() + " finished producing values" + "\nTerminating " + getName() ); }}
public void run() { for ( int count = 1; count <= 10; count++ ) { // sleep for a random interval try { Thread.sleep( (int) ( Math.random() * 3000 ) ); } catch( InterruptedException e ) { System.err.println( e.toString() ); }
pHold.setSharedInt( count ); }
System.err.println( getName() + " finished producing values" + "\nTerminating " + getName() ); }}
Show multiple threads modifying shared object
// Fig. 15.5: SharedCell.java// Show multiple threads modifying shared object.public class SharedCell { public static void main( String args[] ) { HoldIntegerSynchronized h = new HoldIntegerSynchronized(); ProduceInteger p = new ProduceInteger( h ); ConsumeInteger c = new ConsumeInteger( h );
p.start(); c.start(); }}
Definition of threaded class ConsumeInteger
// Fig. 15.6: ConsumeInteger.java// Definition of threaded class ConsumeIntegerimport javax.swing.JTextArea;
public class ConsumeInteger extends Thread { private HoldIntegerSynchronized cHold; private JTextArea output;
public ConsumeInteger( HoldIntegerSynchronized h, JTextArea o ) { super( "ConsumeInteger" ); cHold = h; output = o; }
}
Another run() method
public void run() { int val, sum = 0;
do { // sleep for a random interval try { Thread.sleep( (int) ( Math.random() * 3000 ) ); } catch( InterruptedException e ) { System.err.println( e.toString() ); }
val = cHold.getSharedInt(); sum += val; } while ( val != 10 );
output.append( "\n" + getName() + " retrieved values totaling: " + sum + "\nTerminating " + getName() + "\n" ); }
Definition of class HoldIntegerSynchronized
// Fig. 15.6: HoldIntegerSynchronized.java// Definition of class HoldIntegerSynchronized that// uses thread synchronization to ensure that both// threads access sharedInt at the proper times.import javax.swing.JTextArea;import java.text.DecimalFormat;
public class HoldIntegerSynchronized { private int sharedInt[] = { -1, -1, -1, -1, -1 }; private boolean writeable = true; private boolean readable = false; private int readLoc = 0, writeLoc = 0;}
}
public void displayBuffer( JTextArea out, int buf[] ) { DecimalFormat formatNumber = new DecimalFormat( " #;-#" ); output.append( "\tbuffer: " );
for ( int i = 0; i < buf.length; i++ ) out.append( " " + formatNumber.format( buf[ i ] )); }}
private JTextArea output;
sharedInt[ writeLoc ] = val; readable = true;
output.append( "\nProduced " + val + " into cell " + writeLoc );
writeLoc = ( writeLoc + 1 ) % 5;
output.append( "\twrite " + writeLoc + "\tread " + readLoc); displayBuffer( output, sharedInt );
if ( writeLoc == readLoc ) { writeable = false; output.append( "\nBUFFER FULL" ); }
notify();
public synchronized int getSharedInt() { int val;
while ( !readable ) { try { output.append( " WAITING TO CONSUME" ); wait(); } catch ( InterruptedException e ) { System.err.println( e.toString() ); } }
writeable = true; val = sharedInt[ readLoc ];
output.append( "\nConsumed " + val + " from cell " + readLoc );
readLoc = ( readLoc + 1 ) % 5;
output.append( "\twrite " + writeLoc + "\tread " + readLoc ); displayBuffer( output, sharedInt );
if ( readLoc == writeLoc ) { readable = false; output.append( "\nBUFFER EMPTY" ); }
notify(); return val;
public HoldIntegerSynchronized( JTextArea o ) { output = o; }
public synchronized void setSharedInt( int val ) { while ( !writeable ) { try { output.append( " WAITING TO PRODUCE " + val ); wait(); } catch ( InterruptedException e ) { System.err.println( e.toString() ); } }
Definition of threaded class ProduceInteger
// Fig. 15.6: ProduceInteger.java// Definition of threaded class ProduceIntegerimport javax.swing.JTextArea;
public class ProduceInteger extends Thread { private HoldIntegerSynchronized pHold; private JTextArea output;
public ProduceInteger( HoldIntegerSynchronized h, JTextArea o ) { super( "ProduceInteger" ); pHold = h; output = o; }
public void run() { for ( int count = 1; count <= 10; count++ ) { // sleep for a random interval // Note: Interval shortened purposely to fill buffer try { Thread.sleep( (int) ( Math.random() * 500 ) ); } catch( InterruptedException e ) { System.err.println( e.toString() ); }
pHold.setSharedInt( count ); }
output.append( "\n" + getName() + " finished producing values" + "\nTerminating " + getName() + "\n" ); }}
Multiple threads modifying shared object
// Fig. 15.6: SharedCell.java// Show multiple threads modifying shared object.import java.text.DecimalFormat;import java.awt.*;import java.awt.event.*;import javax.swing.*;
public class SharedCell extends JFrame { public SharedCell() { super( "Demonstrating Thread Synchronization" ); JTextArea output = new JTextArea( 20, 30 );
getContentPane().add( new JScrollPane( output ) ); setSize( 500, 500 ); show();
// set up threads and start threads HoldIntegerSynchronized h = new HoldIntegerSynchronized( output ); ProduceInteger p = new ProduceInteger( h, output ); ConsumeInteger c = new ConsumeInteger( h, output );
p.start(); c.start(); }
public static void main( String args[] ) { SharedCell app = new SharedCell(); app.addWindowListener( new WindowAdapter() { public void windowClosing( WindowEvent e ) { System.exit( 0 ); } } ); }}
Demonstrating the Runnableinterface
// Fig. 15.7: RandomCharacters.java// Demonstrating the Runnableinterfaceimport java.awt.*;import java.awt.event.*;import javax.swing.*;
public class RandomCharacters extends JApplet implements Runnable, ActionListener { private String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private JLabel outputs[]; private JCheckBox checkboxes[]; private final static int SIZE = 3; private Thread threads[]; private boolean suspended[];
public void init() { outputs = new JLabel[ SIZE ]; checkboxes = new JCheckBox[ SIZE ]; threads = new Thread[ SIZE ]; suspended = new boolean[ SIZE ];
Container c = getContentPane(); c.setLayout( new GridLayout( SIZE, 2, 5, 5 ) );
for ( int i = 0; i < SIZE; i++ ) { outputs[ i ] = new JLabel(); outputs[ i ].setBackground( Color.green ); outputs[ i ].setOpaque( true ); c.add( outputs[ i ] );
checkboxes[ i ] = new JCheckBox( "Suspended" ); checkboxes[ i ].addActionListener( this ); c.add( checkboxes[ i ] ); } }
public void start() { // create threads and start every time start is called for ( int i = 0; i < threads.length; i++ ) { threads[ i ] = new Thread( this, "Thread " + (i + 1) ); threads[ i ].start(); } }
public void run() { Thread currentThread = Thread.currentThread(); int index = getIndex( currentThread ); char displayChar;
while ( threads[ index ] == currentThread ) { // sleep from 0 to 1 second try { Thread.sleep( (int) ( Math.random() * 1000 ) );
synchronized( this ) { while ( suspended[ index ] &&threads[ index ] == currentThread ) wait(); } } catch ( InterruptedException e ) { System.err.println( "sleep interrupted" ); } displayChar = alphabet.charAt( (int) ( Math.random() * 26 ) ); outputs[ index ].setText( currentThread.getName() + ": " + displayChar ); }
System.err.println( currentThread.getName() + " terminating" ); }
private int getIndex( Thread current ) { for ( int i = 0; i < threads.length; i++ ) if ( current == threads[ i ] ) return i;
return -1; }
public synchronized void stop() { // stop threads every time stop is called // as the user browses another Web page for ( int i = 0; i < threads.length; i++ ) threads[ i ] = null;
notifyAll(); }
public synchronized void actionPerformed( ActionEvent e ) { for ( int i = 0; i < checkboxes.length; i++ ) { if ( e.getSource() == checkboxes[ i ] ) { suspended[ i ] = !suspended[ i ];
outputs[ i ].setBackground( !suspended[ i ] ? Color.green : Color.red );
if ( !suspended[ i ] ) notify();
return; } } }}