SDSU CS 696 Emerging Technologies: Distributed Objects
Spring Semester, 1998
Java Threads

To Lecture Notes Index
© 1998, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 21-Apr-98

Contents of Doc 14, Java Threads

    1. References
    2. Threads
      1. Creating Threads
      2. Thread Scheduling
        1. Preemptive
        2. Single Processor -Time-slicing or not time-sliced
        3. Native Threads and Parallelism
      3. Simple Yield Example
      4. Sleep Example
    3. Suspend, Resume and Stop
      1. Suspend and Resume
      2. Join - Waiting for Thread to end
    4. Synchronize
    5. DeadLock
    6. Synchonized and Inheritance
    7. wait and notify
      1. wait - How to use
      2. notify - How to Use
    8. The End of an Application
      1. Types of Threads: user and daemon

References


The Java Programming Language, Arnold & Gosling, Addision-Wesley, 1996

Java 1.2b2 on-line documentation

Doc 14, Java Threads Slide # 2

Threads


Thread is a separate process which shares the same name space as the program that created the thread

Difference from fork()

fork()
Child process gets a copy of parents variables
Relatively expensive to start
Don't have to worry about concurrent access to variables

thread
Child process shares parents variables
Relatively cheap to start
Concurrent access to variables is an issue


Thread Class Methods
activeCount()interrupt() setDaemon(boolean)
checkAccess()interrupted() setName(String)
countStackFrames()isAlive() setPriority(int)
currentThread()isDaemon() sleep(long)
destroy()isInterrupted() sleep(long, int)
dumpStack()join() start()
enumerate(Thread[])join(long) stop()
getName()join(long, int) stop(Throwable)
getPriority()resume() suspend()
getThreadGroup()run() toString()
yeild()


Doc 14, Java Threads Slide # 3

Creating Threads


There are two different methods for creating a thread
class  SimpleThread  extends Thread
   {
   public  void run()
      {
      for  ( int  count = 0;  count < 4; count++)
         System.out.println( "Message " + count +
                          "From: Mom" );
      }
   }

class  TestThread
   {
   public static void main( String[]  args )
      {
      SimpleThread  parallel  = new SimpleThread();
      System.out.println( "Create the thread");
      parallel.start();
      System.out.println( "Started the thread" );
      System.out.println( "End" );
      }
   }
Output
Create the thread
Started the thread
End
Message 0From: Mom
Message 1From: Mom
Message 2From: Mom
Message 3From: Mom

Doc 14, Java Threads Slide # 4
Second Method for Creating a Thread

class  SecondMethod  implements  Runnable
   {
   public  void  run()
      {
      for  ( int  count = 0;  count < 4; count++)
         System.out.println( "Message " + count +  " From: Dad");
      }
   }

class  TestThread
   {
   public static void main( String[]  args )
      {
      SecondMethod  notAThread  = new SecondMethod();
      Thread  parallel  =  new Thread( notAThread );

      System.out.println( "Create the thread");
      parallel.start();
      System.out.println( "Started the thread" );
      System.out.println( "End" );
      }
   }
Output
Create the thread
Started the thread
End
Message 0 From: Dad
Message 1 From: Dad
Message 2 From: Dad
Message 3 From: Dad

Doc 14, Java Threads Slide # 5
Giving a Thread a Name

class  SecondMethod  implements  Runnable
   {
   public  void  run()
      {
      for  ( int  count = 0;  count < 4; count++)
         System.out.println( "Message " + count +  " From: " + 
                        Thread.currentThread().getName() );
      }
   }

class  TestThread
   {
   public static void main( String[]  args )
      {
      SecondMethod  notAThread  = new SecondMethod();
      Thread  parallel  =  new Thread( notAThread, "Mom" );

      System.out.println( "Create the thread");
      parallel.start();
      System.out.println( "Started the thread" );
      System.out.println( "End" );
      }
   }
Output
Create the thread
Started the thread
End
Message 0 From: Mom
Message 1 From: Mom
Message 2 From: Mom
Message 3 From: Mom

Doc 14, Java Threads Slide # 6
SimpleThread for Use in Future Examples
class  SimpleThread  extends Thread
   {
   private  int  maxCount =  32;

   public  SimpleThread(  String  name )
      {
      super( name );
      }

   public  SimpleThread(  String  name, int repetitions )
      {
      super( name );
      maxCount  =  repetitions;
      }

   public  SimpleThread(  int repetitions )
      {
      maxCount  =  repetitions;
      }


   public  void run()
      {
      for  ( int  count = 0;  count < maxCount; count++)
         {
         System.out.println( count + " From: " + getName() );
         }
      }
   }


Doc 14, Java Threads Slide # 7
Show Some Parallelism?

class  TestThread
   {
   public static void main( String[]  args )
      {
      SimpleThread  first      = new SimpleThread( 5 );
      SimpleThread  second  = new SimpleThread( 5 );
      first.start();
      second.start();
      System.out.println( "End" );
      }
   }


Output- Rohan Native Threads
End
0 From: Thread-3
0 From: Thread-2
1 From: Thread-3
2 From: Thread-3
1 From: Thread-2
3 From: Thread-3
2 From: Thread-2
4 From: Thread-3
3 From: Thread-2
4 From: Thread-2

Doc 14, Java Threads Slide # 8

Thread Scheduling

Preemptive

Priorities

A thread is run before other threads with lower priorities
public final static int MIN_PRIORITY = 1
public final static int NORM_PRIORITY = 5
public final static int MAX_PRIORITY = 10

class  TestThread
   {
   public static void main( String[]  args )
      {
      SimpleThread  first      = new SimpleThread( 5 );
      SimpleThread  second  = new SimpleThread( 5 );
      second.setPriority( 8 );
      first.start();
      second.start();
      System.out.println( "End" );
      }
   }
Output
On Single ProcessorOn Multiple Processor Rohan
0 From: Thread-5End
1 From: Thread-50 From: Thread-3
2 From: Thread-51 From: Thread-3
3 From: Thread-52 From: Thread-3
4 From: Thread-50 From: Thread-2
0 From: Thread-43 From: Thread-3
1 From: Thread-41 From: Thread-2
2 From: Thread-42 From: Thread-2
3 From: Thread-44 From: Thread-3
4 From: Thread-43 From: Thread-2
End4 From: Thread-2


Doc 14, Java Threads Slide # 9
Thread Scheduling

Single Processor -Time-slicing or not time-sliced


Time-slicing
a thread is run for a short time slice and suspended,
resumes only when it gets its next "turn"
threads of the same priority share turns
Java does not specify if the scheduler does time-slicing

Java running green-threads Solaris does not time-slice

Non time-sliced threads run until:
they end
they are terminated
they are interrupted
Higher priority threads interrupts lower priority threads
they go to sleep
they block on some call
reading a socket
waiting for another thread
they yield


Doc 14, Java Threads Slide # 10

Native Threads and Parallelism


Starting with Solaris 2.6 (or Solaris 2.5 with proper patches) java supports the use of native Solaris threads

On multiprocessor machines native Solaris threads may be scheduled on different processors - depends on load of each processor

The default is for java to use green-threads

To use native threads use:
java -native className

The default version of java on rohan (1.1.3) is set up to run native threads only
Methods of Interest
destroy()sleep(long)
interrupt() sleep(long, int)
join() stop()
join(long) stop(Throwable)
join(long, int) suspend()
yield()

Doc 14, Java Threads Slide # 11
Testing for Time-slicing & Parallelism
class  InfinityThread  extends Thread
   {
   public  void run()
      {
      while ( true )
         System.out.println(  "From: " + getName() );
      }
   }

class  TestThread
   {
   public static void main( String[]  args )
      {
      InfinityThread  first      = new InfinityThread( );
      InfinityThread  second  = new InfinityThread( );
      first.start();
      second.start();
      }
   }

Output if Time-sliced

A group of "From: Thread-5" will be followed by a group of "From: Thread-4" etc.

Output if not Time-sliced, Single Processor

"From: Thread-4" will repeat "forever"
Multiple Processor
"From: Thread-5" and "From: Thread-4" will intermix "forever"


Doc 14, Java Threads Slide # 12

Simple Yield Example

class  YieldThread  extends Thread
   {
   public  void run()
      {
      for  ( int  count = 0;  count < 4; count++)
         {
         System.out.println( count + "From: " + getName() );
         yield();
         }
      }
   }

class  TestThread
   {
   public static void main( String[]  args ) 
      {
      YieldThread  first      = new YieldThread();
      YieldThread  second  = new YieldThread();

      first.start();
      second.start();
      System.out.println( "End" );
      }
   }
Output - Single and Multiple Processors
End
0From: Thread-2
0From: Thread-3
1From: Thread-2
1From: Thread-3
2From: Thread-2
2From: Thread-3
3From: Thread-2
3From: Thread-3

Doc 14, Java Threads Slide # 13

Sleep Example


class  SleepyThread  extends Thread
   {
   int maxCount = 4;
   public  SleepyThread(  String  name, int count )
      {
      super( name );
      maxCount = count;
      }

   public  void run()
      {
      for  ( int  count = 0;  count < 4; count++)
         {
         System.out.println( count + " From: " + getName() );

         try
            {
            sleep( 5 );   // in  milliseconds
            }

         catch  ( InterruptedException ignored )  {}
         }
      }
   }


Doc 14, Java Threads Slide # 14
// Sleep Example Continued
class  TestSleep
   {
   public static void main( String[]  args )
      {
      SimpleThread  alert    = new SimpleThread( "Alert", 32 );
      SleepyThread  sleepy  = new SleepyThread( "Sleepy", 32 );
      sleepy.setPriority( 8 );
      alert.start();
      sleepy.start();
      System.out.println( "End" );
      }
   }
Output
0 From: Sleepy17 From: Alert
0 From: Alert18 From: Alert
1 From: Alert19 From: Alert
2 From: Alert20 From: Alert
3 From: Alert21 From: Alert
4 From: Alert22 From: Alert
5 From: Alert23 From: Alert
6 From: Alert24 From: Alert
7 From: Alert25 From: Alert
8 From: Alert26 From: Alert
9 From: Alert27 From: Alert
10 From: Alert28 From: Alert
11 From: Alert2 From: Sleepy
12 From: Alert29 From: Alert
13 From: Alert30 From: Alert
14 From: Alert31 From: Alert
1 From: Sleepy3 From: Sleepy
End
15 From: Alert
16 From: Alert


Doc 14, Java Threads Slide # 15

A Clock Example
class Clock extends Thread
   {
   static int millisecondsHour = 1000 * 60 * 60;
   static long millisecondsPerDay = millisecondsHour * 24;
   
   int millSecondsPerSimDay;
   Date simDate = new Date();

   public Clock( int simDaysPerHour )
      {
      millSecondsPerSimDay  = millisecondsHour / simDaysPerHour;
      setPriority( Thread.MAX_PRIORITY );
      }
   
   public String toString() { return simDate.toString(); }
      
   public void run()
      {
      try
         {
         while (true)
            {
            // Advance one sim day
            long simTime = simDate.getTime();
            simDate.setTime( simTime + millisecondsPerDay);
            // wait until next day
            sleep( millSecondsPerSimDay );
            }
         }
      catch ( InterruptedException simulationOver )
         { return;}
      }
   }


Doc 14, Java Threads Slide # 16
Using Clock

import sdsu.io.Console;
import java.util.Date;

class Test
   {
   public static void main(String  args[] ) throws Exception
      {
      Clock fast = new Clock( 60 * 60 * 10 );
      fast.start();
      for ( int k = 0; k < 5; k++ )
         {
         System.out.println( fast.toString());
         Console.readInt( "Type an int" );
         }
      fast.stop();
      }   
   
   }
Output
rohan 24-> java Test
Thu Feb 13 17:19:11 PST 1997
Type an int 12
Fri Feb 28 17:19:11 PST 1997
Type an int 21
Mon Mar 24 17:19:11 PST 1997
Type an int 12
Thu Apr 10 18:19:11 PDT 1997
Type an int 12
Fri May 02 18:19:11 PDT 1997
Type an int 12

Doc 14, Java Threads Slide # 17
Setting Priorities

Continuously running parts of the program should have lower-priority than rarer events

User input should have very high priority

A thread that continually updates some data is often set to run at MIN_PRIORITY

Doc 14, Java Threads Slide # 18

Suspend, Resume and Stop


These methods are deprecated in JDK 1.2 because they are not thread safe

Start avoiding these methods now!

Doc 14, Java Threads Slide # 19
Ending Thread Execution

A thread ends when its run method returns
Forcing a Thread to Quit
The Preferred Way

Running thread checks to see if it is time to stop
class Test {
   public  static  void  main( String  args[] ) throws Exception{
      NiceThread  missManners  = new NiceThread( );
      missManners.setPriority( 2 );
      missManners.start();
      Thread.currentThread().sleep( 5 );
      missManners.pleaseStop();
   }
}

class  NiceThread  extends Thread {
   protected boolean stopRequested = false;
   
   public void pleaseStop() { stopRequested = true; }

   public void run() {
      while (!stopRequested)
         System.out.println(  "From: " + getName()  );
      System.out.println( "The End" );
   }
}
Output
From: Thread-2
From: Thread-2
From: Thread-2
From: Thread-2
From: Thread-2
The End

Doc 14, Java Threads Slide # 20
What if the Thread is waiting?

If a thread is waiting for other event it will not respond to the pleaseStop method until after the event

If the other event never happens or occurs after a long time, then the pleaseStop is not useful

In these cases use interrupt


Doc 14, Java Threads Slide # 21
 class Test {
   public  static  void  main( String  args[] ) throws Exception{
      OccupiedThread  missManners  = new OccupiedThread ( );
      missManners.setPriority( 2 );
      missManners.start();
      Thread.currentThread().sleep( 5 );
      missManners.interrupt();
   }
}
class  OccupiedThread  extends Thread {
   protected boolean stopRequested = false;
   
   public void pleaseStop() { stopRequested = true; }

   public void run() {
      try {
         while (!stopRequested) {
            read();
            System.out.println(  "From: " + getName()  );
         }
         System.out.println( "The End" );
      }
      catch (InterruptedException threadInterrupted) {
         System.out.println( "Good bye" );
      }
      catch (IllegalMonitorStateException threadInterrupted) {
      System.out.println( "Dear me" );
      }
   }
   
   public void read() throws InterruptedException {
      System.out.println( "In read" );
      wait();
   }
}

Doc 14, Java Threads Slide # 22
Trouble In thread Land
class Test {
   public  static  void  main( String  args[] ) throws Exception{
      TroubleThread  missManners  = new TroubleThread( );
      missManners.setPriority( 2 );
      missManners.start();
      Thread.currentThread().sleep( 5 );
      missManners.interrupt(); //Does not work
   }
}

class  TroubleThread  extends Thread {
   protected boolean stopRequested = false;
   public void pleaseStop() { stopRequested = true; }

   public void run() {
      try{
         while (!stopRequested) {
            read();
         }
      }
      catch (InterruptedException threadInterrupted){
         System.out.println( "Good bye" );
      }
      catch (IllegalMonitorStateException threadInterrupted) {
         System.out.println( "Dear me" );
      }
   }
   
   public void read() throws InterruptedException {
      try{
         System.out.println( "In read" );
         int input = System.in.read();   //Don't type anything
      }
      catch (IOException readError){}
   }
}

Doc 14, Java Threads Slide # 23
Forcing a Thread to QuitStop
DO NOT USE THIS METHOD
class Test {
   public  static  void  main( String  args[] ) throws Exception{
      TroubleThread  missManners  = new TroubleThread( );
      missManners.setPriority( 2 );
      missManners.start();
      Thread.currentThread().sleep( 5 );
      missManners.stop();          //This works
   }
}

Doc 14, Java Threads Slide # 24
Forcing a Thread to Quit
The Rambo Way
destroy

destroy method was never implemented and will not be.


Doc 14, Java Threads Slide # 25

Suspend and Resume

class  Suspended
   {
   public static void main( String[]  args ) throws 
      InterruptedException
      {
      SimpleThread  alert      = new SimpleThread( "Alert" );
      SleepyThread  sleepy  = new SleepyThread( "Sleepy" );
      sleepy.setPriority( 8 );
      alert.start();
      sleepy.start();

      sleepy.suspend();
      System.out.println( "now I can go" );
      Thread.sleep( 4 );
      sleepy.resume();
      }
   }
Output
0 From: Sleepy12 From: Alert26 From: Alert
0 From: Alert13 From: Alert27 From: Alert
1 From: Alert14 From: Alert28 From: Alert
2 From: Alert15 From: Alert29 From: Alert
3 From: Alert16 From: Alert30 From: Alert
4 From: Alert17 From: Alert31 From: Alert
5 From: Alert18 From: Alert3 From: Sleepy
6 From: Alert19 From: Alert
7 From: Alert20 From: Alert
8 From: Alert21 From: Alert
9 From: Alert22 From: Alert
1 From: Sleepy23 From: Alert
now I can go24 From: Alert
10 From: Alert2 From: Sleepy
11 From: Alert25 From: Alert


Doc 14, Java Threads Slide # 26

Join - Waiting for Thread to end

class  Godot
   {
   public static void main( String[]  args ) throws 
      InterruptedException
      {
      SimpleThread  lowly      = new SimpleThread( "Lowly" );
      lowly.setPriority( 1 );
      lowly.start();

      System.out.println( "now I can go" );

      lowly.join();

      System.out.println( "Done" );
      }
   }

Output

now I can go11 From: Lowly23 From: Lowly
0 From: Lowly12 From: Lowly24 From: Lowly
1 From: Lowly13 From: Lowly25 From: Lowly
2 From: Lowly14 From: Lowly26 From: Lowly
3 From: Lowly15 From: Lowly27 From: Lowly
4 From: Lowly16 From: Lowly28 From: Lowly
5 From: Lowly17 From: Lowly29 From: Lowly
6 From: Lowly18 From: Lowly30 From: Lowly
7 From: Lowly19 From: Lowly31 From: Lowly
8 From: Lowly20 From: LowlyDone
9 From: Lowly21 From: Lowly
10 From: Lowly22 From: Lowly


Doc 14, Java Threads Slide # 27

Synchronize


With multiprocessing we need to address mutual exclusion

What happens when two threads access the same:
method?
data?

class  AccessExample
   {
   public  int[]  data  =  new  int[10];

   public  safeCode( int Size,  int  startValue)
      {
      int[]  verySafe  =  new  int[ Size ]; 

      for  ( int  index  = 0; index < Size;  index++ )
         verySafe[ index ]  =  (int ) Math.sin( index * startValue );
      }

   public  dangerousCode( int Size,  int  startValue)
      {
      for  ( int  index  = 0; index < Size;  index++ )
         data[ index ]  =  (int ) Math.sin( index * startValue );
      }
   }

Java uses "Synchronized" code to insure that only one thread at a time will use a section of critical code

Doc 14, Java Threads Slide # 28
Synchronize Syntax
class  SynchronizeSyntax
   {
   protected  int myValue;
   public  static  int  globalStuff;

   public  synchronized  void  synchronizedMethod()
      {
      myValue++;
      }

   public  ShowSynchronizedBlock(  Vector  criticalData  )
      {
      // Some non-critical code can go here

      synchronized (  criticalData  )
         {
         // put critical code here
         }

      // More non-critical code can go here
      }

   public  SynchronizedClass(  )
      {
      // Some non-critical code can go here

      synchronized (  getClass()  )
         {
         // put critical code here
         }

      // More non-critical code can go here
      }
   }

Doc 14, Java Threads Slide # 29
Synchronized Example
class  Loop   {
   public  void  doLoop( int size, String name )  {
      for  ( int  count = 0;  count < size; count++) {
         System.out.println( count + " From: " + name );
         double wasteTime  =  Math.sin( Math.cos ( count ) );
      }
   }
}

class  SyncLoop  extends  Loop {
   public  synchronized  void  doLoop( int size, String name )  {
      for  ( int  count = 0;  count < size; count++) {
         System.out.println( count + " From: " + name );
         double wasteTime  =  Math.sin( Math.cos( count ) );
      }
   }
   public void unprotected()
      { System.out.println( "From unprotected" ); }
   }

class Cheat extends Loop   {
   SyncLoop myReference;

   public Cheat( SyncLoop aReference ) {
      myReference = aReference;
   }
   public  void  doLoop( int size, String name )  {
      for  ( int  count = 0;  count < size; count++) 
         myReference.unprotected();
   }
}


Doc 14, Java Threads Slide # 30
// Synchronized Example Continued

class  SimpleThread  extends Thread
   {
   private  int  maxCount;
   private  Loop  myCopyOfLoop;


   public  SimpleThread(  String  name, int count, Loop  copy )
      {
      super( name );
      maxCount  =  count;
      myCopyOfLoop  =  copy;
      }


   public  void  run()
      {
      myCopyOfLoop.doLoop( maxCount, getName() );
      }
   }


Doc 14, Java Threads Slide # 31
// Synchronized Example Continued

class  SleepyThread  extends Thread
   {
   private  Loop  myCopyOfLoop;
   private  int  maxCount;

   public  SleepyThread(  String  name, int count,  Loop  copy )
      {
      super( name );
      maxCount  =  count;
      myCopyOfLoop  =  copy;
      }


   public  void run()
      {
      for  ( int  count = 0;  count < 4; count++)
         {
         try
            {
            sleep( 5 );   // in  milliseconds
            myCopyOfLoop.doLoop( maxCount, getName() );
            }
         catch  ( InterruptedException ignored )  {}
         }
      }
   }


Doc 14, Java Threads Slide # 32
// Synchronized Example Continued


class  TestNoSynch
   {
   public static void main( String[]  args ) throws Exception
      {
      Loop  notSafe  =  new Loop();
      SimpleThread  alert;
      SleepyThread  sleepy;

      alert  = new SimpleThread( "Alert", 8, notSafe );
      sleepy  = new SleepyThread( "Sleepy", 2, notSafe );

      sleepy.setPriority( 8 );
      alert.start();
      sleepy.start();
      System.out.println( "End" );
      }
   }

Output
0 From: Alert6 From: Alert
1 From: Alert7 From: Alert
2 From: Alert0 From: Sleepy
0 From: Sleepy1 From: Sleepy
1 From: Sleepy0 From: Sleepy
End1 From: Sleepy
3 From: Alert0 From: Sleepy
4 From: Alert1 From: Sleepy
5 From: Alert


Doc 14, Java Threads Slide # 33
// Synchronized Example Continued

class  TestSynch
   {
   public static void main( String[]  args ) throws Exception
      {
      Loop  safe  =  new SyncLoop();
      SimpleThread  alert;
      SleepyThread  sleepy;

      alert  = new SimpleThread( "Alert", 8, safe  );
      sleepy  = new SleepyThread( "Sleepy", 2, safe  );

      sleepy.setPriority( 8 );
      alert.start();
      sleepy.start();
      System.out.println( "End" );
      }
   }

Output
0 From: Alert1 From: Sleepy
1 From: AlertEnd
2 From: Alert0 From: Sleepy
3 From: Alert1 From: Sleepy
4 From: Alert0 From: Sleepy
5 From: Alert1 From: Sleepy
6 From: Alert0 From: Sleepy
7 From: Alert1 From: Sleepy
0 From: Sleepy


Doc 14, Java Threads Slide # 34
// Synchronized Example Continued

class  TestUnsynchedMethod
   {
   public static void main( String[]  args ) throws Exception
      {
      SyncLoop  safe  =  new SyncLoop();
      Cheat  ohNo = new Cheat( safe);
      SimpleThread  alert;
      SleepyThread  sleepy;

      alert  = new SimpleThread( "Alert", 16, safe  );
      sleepy  = new SleepyThread( "Sleepy", 2, ohNo );

      sleepy.setPriority( 8 );
      alert.start();
      sleepy.start();
      System.out.println( "End" );
      }
   }
Output
End7 From: Alert
From unprotected8 From: Alert
From unprotected9 From: Alert
0 From: Alert10 From: Alert
From unprotected11 From: Alert
From unprotectedFrom unprotected
1 From: AlertFrom unprotected
2 From: Alert12 From: Alert
3 From: Alert13 From: Alert
4 From: Alert14 From: Alert
5 From: Alert15 From: Alert
6 From: Alert16 From: Alert


Doc 14, Java Threads Slide # 35

DeadLock

class  Friendly  extends Thread {
   private  Friendly  aFriend;

   public  Friendly(  String  name ) {   super( name ); }

   public void setFriend( Friendly myFriend )
      { aFriend = myFriend;}
      
   public synchronized void hug() {
      try {
         System.out.println(  "I " + getName() + " am hugged ");
         sleep( 5 );
         aFriend.rehug();
      } catch ( InterruptedException notInThisExample ){}
   }

   public synchronized void rehug() {
      System.out.println( "I " + getName() + " am rehugged ");
   }
      
   public  void  run()   {aFriend.hug(); }
}

public class Test {
   public static void main( String args[] )  {
      Friendly  fred  =  new Friendly("Fred");
      Friendly  sam = new Friendly( "Sam");
      fred.setFriend( sam );
      sam.setFriend( fred );
      fred.start();
      sam.start();
      System.out.println( "End" );
      }
   }
Output
End
I Fred am hugged
I Sam am hugged

Doc 14, Java Threads Slide # 36
Deadlock Avoided

class  Friendly  extends Thread   {
   private  Friendly  aFriend;
   private Object lock;

   public  Friendly(  String  name, Object lock )   {
      super( name );
      this.lock = lock;
   }

   public void setFriend( Friendly myFriend )   {
      aFriend = myFriend;
   }
      
   public synchronized void hug()    {
      try {
         System.out.println(  "I " + getName() + " am hugged ");
         sleep( 5 );
         aFriend.rehug();
      }
      catch ( InterruptedException notInThisExample ) {}
   }

   public synchronized void rehug()   {
      System.out.println( "I " + getName() + " am rehugged ");
   }
      
   public  void  run()    {
      synchronized ( lock)   {
         aFriend.hug();
      }
   }
}

Doc 14, Java Threads Slide # 37
//Deadlock Avoided Continued

public class Test
   {

   public static void main( String args[] ) //throws Exception
      {
      Object aLock = "Schalage";
      Friendly  fred  =  new Friendly("Fred", aLock);
      Friendly  sam = new Friendly( "Sam", aLock);
      fred.setFriend( sam );
      sam.setFriend( fred );
      fred.start();
      sam.start();
      System.out.println( "End" );
      }
   }

Output
End
I Sam am hugged
I Fred am rehugged
I Fred am hugged
I Sam am rehugged


Doc 14, Java Threads Slide # 38

Synchonized and Inheritance

class Top
   {
   public void synchronized left()
      {
      // do stuff
      }

   public void synchronized right()
      {
      // do stuff
      }
   }

class Bottom extends Top
   {
   public void left()
      {
      // not synchronized 
      }

   public void right()
      {
      // do stuff not synchronized
      super.right();   // synchronized here
      // do stuff not synchronized
      }

If you want a method in a subclass to be synchronized you must declare it to be synchronized.

Doc 14, Java Threads Slide # 39
Synchonized and Static Methods

Two threads can not execute synchronized static methods on the same class at the same time.

The lock for a static method has no effect on any of the objects of that class.


Doc 14, Java Threads Slide # 40

wait and notify

class Queue
   {
   LinkedCell head;
   LinkedCell tail;
   
   public synchronized void append( Object item )
      {
      LinkedCell  newItem = new LinkedCell( item );

      if ( head == null )
         head = newItem;
      else
         tail.append( newItem );

      tail = newItem;
      notify();
      }

   public synchronized Object get( )
      {
      try
         {
         while ( head == null )
            wait();
         }
      catch (InterruptedException threadIsDone )
         {
         return null;
         }
      
      Object returnMe = head.element();
      head = head.next();
      return returnMe;
      }
   }

Doc 14, Java Threads Slide # 41
wait and notify - Helper
class LinkedCell
   {
   Object cellItem;
   LinkedCell next;

   public LinkedCell( Object value )
      {
      cellItem= value;
      }

   public Object element()
      { 
      return cellItem;
      }

   public void append( LinkedCell nextCell )
      {
      next = nextCell;
      }

   public LinkedCell next()
      { 
      return next; 
      }
   }



Doc 14, Java Threads Slide # 42
wait and notify - Producer

class Producer extends Thread
   {
   Queue factory;
   int workSpeed;
   
   public Producer( String name, Queue output, int speed )
      {
      setName(name);
      factory = output;
      workSpeed = speed;
      }
   
   public void run()
      {
      try
         {
         int product = 0;
         while (true) // work forever
            {
            System.out.println( getName() + " produced " + product);
            factory.append( getName() + String.valueOf( product) );
            product++;
            sleep( workSpeed);
            }
         }
      catch ( InterruptedException WorkedToDeath )
         { 
         return;
         }
      }
   }
   
   

Doc 14, Java Threads Slide # 43
wait and notify - Consumer

class Consumer extends Thread
   {
   Queue localMall;
   int sleepDuration;
   
   public Consumer( String name, Queue input, int speed )
      {
      setName(name);
      localMall = input;
      sleepDuration = speed;
      }
   
   public void run()
      {
      try
         {
         while (true) // Shop until you drop
            {
            System.out.println( getName() + " got " + 
                              localMall.get());
            sleep( sleepDuration );
            }
         }
      catch ( InterruptedException endOfCreditCard )
         { 
         return;
         }
      }
   }


Doc 14, Java Threads Slide # 44
wait and notify - Driver Program

class Test
   {
   public  static  void  main( String  args[] ) throws Exception
      {
      Queue wallmart = new Queue();
      Producer nike = new Producer( "Nike", wallmart, 500 );
      Producer honda = new Producer( "Honda", wallmart, 1200 );
      Consumer valleyGirl = new Consumer( "Sue", wallmart, 400);
      Consumer valleyBoy = new Consumer( "Bob", wallmart, 900);
      Consumer dink = new Consumer( "Sam", wallmart, 2200);
      nike.start();
      honda.start();
      valleyGirl.start();
      valleyBoy.start();
      dink.start();
      }
   }
Output
Nike produced 0Sue got Nike3Honda produced 3
Honda produced 0Nike produced 4Bob got Honda3
Sue got Nike0Sue got Nike4Nike produced 8
Bob got Honda0Honda produced Sue got Nike8
Nike produced 1Bob got Honda2Nike produced 9
Sam got Nike1Nike produced 5Sue got Nike9
Nike produced 2Sue got Nike5Honda produced 4
Sue got Nike2Nike produced 6Bob got Honda4
Honda produced 1Sam got Nike6Nike produced 10
Bob got Honda1Nike produced 7Sue got Nike10
Nike produced 3Sue got Nike7Nike produced 11


Doc 14, Java Threads Slide # 45

wait - How to use


The thread waiting for a condition should look like:
synchronized void waitingMethod()
   {
   while ( ! condition )
      wait();

   Now do what you need to do when condition is true
   }
Note

Everything is executed in a synchronized method

The test condition is in loop not in an if statement

The wait suspends the thread it atomically releases the lock on the object

Doc 14, Java Threads Slide # 46

notify - How to Use

synchronized void changeMethod()
   {
   Change some value used in a condition test

   notify();
   }


Doc 14, Java Threads Slide # 47
wait and notify Methodsin Object

public final void wait(timeout) throws InterruptedException
Causes a thread to wait until it is notified or the specified timeout expires.
Parameters:
timeout - the maximum time to wait in milliseconds
Throws: IllegalMonitorStateException
If the current thread is not the owner of the Object's monitor.
Throws: InterruptedException
Another thread has interrupted this thread.

public final void wait(timeout, nanos) throws InterruptedException
public final void wait() throws InterruptedException

public final void notify()
public final void notifyAll()
Notifies all of the threads waiting for a condition to change. Threads that are waiting are generally waiting for another thread to change some condition. Thus, the thread effecting a change that more than one thread is waiting for notifies all the waiting threads using the method notifyAll(). Threads that want to wait for a condition to change before proceeding can call wait(). The method notifyAll() can only be called from within a synchronized method.


Doc 14, Java Threads Slide # 48

The End of an Application


When an program creates threads, what happens when the main ends before the other threads?

Types of Threads: user and daemon


A program ends when the last user thread is finished

All daemon threads running when the program ends are stopped


Doc 14, Java Threads Slide # 49
Daemon example
class Test
   {
   public  static  void  main( String  args[] ) throws Exception{
      InfinityThread  shortLived      = new InfinityThread( );
      shortLived.setDaemon( true );
      shortLived.start();
      Thread.currentThread().sleep( 10 );
      System.out.println( "Bye");
      }
   }

class  InfinityThread  extends Thread
   {
   public  void run()
      {
      while (true)
         {
         System.out.println(  "From: " + getName()  );
         System.out.flush();
         yield();
         }
      }
   }
Output
From: Thread-4
From: Thread-4
From: Thread-4
From: Thread-4
From: Thread-4
From: Thread-4
From: Thread-4
From: Thread-4
From: Thread-4
Bye


Doc 14, Java Threads Slide # 50
Debugging Threads

Some useful methods in Thread for debugging


public static void dumpStack()
Prints a stack trace for the current thread on System.out


public String toString()
Returns a String representation of the Thread, including the thread's name, priority and thread group.


public int countStackFrames()
Returns the number of stack frames in this Thread. The Thread must be suspended when this method is called.


visitors since 24-Feb-98