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.
|