32
Java threads Threaded class extends thread Synchronized class is a monitor Runnable interface gives thread methods All code is (C) Copyright 1999 by Deitel & Associates, Inc. and Prentice Hall.

Java threads Threaded class extends thread Synchronized class is a monitor Runnable interface gives thread methods All code is (C) Copyright 1999 by Deitel

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; } } }}