Threads in Java

About Threads

Java threads are units of a Java computation executing Java methods. Java Virtual Machines support concurrent execution of Java threads. Such multithreading is pre-emptive and prioritised. Scheduling is regulated by priorities:

  • all threads have priority from 1 to 10
  • threads are given by default a priority of 5
  • new threads inherit the priority of their creating thread

Java scheduler

  • keeps highest priority thread running at all times
  • pre-empts current thread if higher priority one is ready

When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically calls the method named main of some designated class). The Java Virtual Machine (the scheduler) continues to execute threads until either of the following occurs:

  • The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
  • All threads that are not daemon threads have died, either by returning from the call to the run method or by performing the stop method.

 

Some but not all Java schedulers support time-slicing

  • while multiple threads are ready and have highest priority
  • successive such threads are run for timeslice and then pre-empted
  • scheduling chances continue to be distributed round robin fashion

 

Otherwise yield() method

  • allows thread to give way to other equal priority threads
  • should be periodically used when there is no time-slicing

Threads can be created by

  • passing runnable object to thread constructor
  • subclassing Thread so it defines its own run() method

Main methods of Java threads are:

getPriority() gets priority of thread

interrupt() wakes sleep/waiting thread via InterruptedException sets interrupted flag on non-sleeping thread

run() body of thread

resume() restarts suspended thread

setPriority() sets priority of thread

sleep(msecs) makes thread sleep for msecs milliseconds

start() initiates thread by executing its run() method

suspend() temporarily suspends thread until resumed

yield() gives way to equal priority threads on scheduling

Three useful inherited methods from Object class are

notify() unblocks waiting thread

notifyAll() unblocks waiting threads

wait() blocks object until notified

Sometimes a thread needs to wait for another thread to do something before it can continue. The methods wait() and notify(), which are defined in class Object and thus inherited by all classes, are made for this purpose. They can only be called from within synchronized methods. A call to wait() releases the monitor lock and puts the calling thread to sleep (i.e., it stops running). A subsequent call to notify on the same object wakes up a sleeping thread and lets it start running again. If more than one thread is sleeping, one is chosen arbitrarily3 no threads are sleeping in this object, notify() does nothing.

The method notifyAll is similar, but wakes up all threads sleeping in the object.

 

Java Thread Synchronisation

 

Thread executes until it

  • blocks on input/output
  • calls sleep(), suspend(), stop(), wait() or yield()
  • is delayed on call to synchronised method
  • is pre-empted by higher priority thread
  • uses up its time-slice

Higher priority thread other than running thread can become ready if

  • suspended thread is resumed
  • sleeping thread finishes sleeping
  • it is waiting on I/O which completes
  • waiting thread has notify or notifyAll called on it

2 Alternatives to create a Thread

 

1) class extends 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" );

}

}

 

2) class implements Runnable, and then create instance of it and pass this to the general Thread constructor and start this 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" );

}

}

 

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.
  • if not Time-sliced, Single Processor "From: Thread-4" will repeat "forever"
  • Multiple Processor "From: Thread-5" and "From: Thread-4" will intermix "forever"

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.

 

 

 

© Lynne Grewe 2001