Definition: A thread is nothing but a single sequential flow of control within the program.
A D V E R T I S E M E N T
What is Thread?
Programmers are familiar with writing sequential programs. The program that displays
"Hello World!", or program which sorts a list of names, or computes the list of
prime numbers, are sequential all programs: each has beginning, end, sequence,
and at any given time during runtime of program there is single point of execution.
A thread is similar to a sequential program, a single thread do also has
beginning, end, sequence, and at any given time during runtime of thread
there will be a single point of execution. But the thread itself is not a
program it cannot run by itself but runs within the program.
Simple Thread example
The following example is a simple Java application that will create and start two
independent threads.
class TwoThreadsTest
{
public static void main (String args[])
{
new SimpleThread("Japan").start();
new SimpleThread("India").start();
}
}
class SimpleThread extends Thread
{
public SimpleThread(String str)
{
super(str);
}
public void run()
{
for (int i = 0; i < 10; i++)
{
System.out.println(i + " " + getName());
try
{
sleep((int)(Math.random() * 1000));
} catch (InterruptedException e)
{}
}
System.out.println("DONE! " + getName());
}
}
The first method in SimpleThread class is a constructor which takes only String as its
argument. This constructor is implemented by calling the superclass constructor and
is interesting because it sets Thread's name which is been used later in the program.
The next method in this class is run() method. run() method is the
heart of any Thread, this is where the action of the Thread takes place. The run() method
in the SimpleThread class contains a for loop which iterates ten times. In each of the
iteration it displays the iteration number and name of the Thread and then sleeps for
random interval of time between 0 and 1 second. After finishing the loop, the run() method
prints "DONE!" along with the name of thread.
Attributes of a Thread
All the action takes place in the thread's body, in the thread's run() method. We can
provide the body to Thread in one of the two ways: first by subclassing a Thread class
and overriding the run() method of thread, secondly by creating a Thread with
Runnable object as its target.
Body of a Thread
Java threads are implemented by using Thread class which is the part of java.lang package.
A Thread class implements the system independent definition of Java threads. But,
actual implementation of the concurrent operation is provided by the
system-specific implementation. For most of the programming needs, underlying
implementation doesn't matter; we can ignore the underlying implementation and
program the thread API and other documentation provided with the Java system.
States of a Thread
Throughout the life, Java thread will be in one among several states. The state of a thread
indicates what the Thread is doing currently and what it can do at that time of
its life: whether it is running? is sleeping? or is dead? These states are illustrated
below.
New Thread
The statement below creates a new thread but it will not start it thereby leaving
the thread in a state labeled "New Thread".
Thread myThread = new MyThreadClass();
When the thread is in "New Thread" state, merely it is an empty Thread object. No
system resources are allocated for it yet. Thus when the thread is in this state,
we can only start or stop the thread; when a thread is in this state calling any of the
other method besides start() or stop() will not make any sense and causes an
IllegalThreadStateException.
Runnable
The start() method creates all the necessary system resources to run a thread, It schedules
the thread to run, and calls thread's run() method.
Thread myThread = new MyThreadClass();
myThread.start();
At this point the thread is in "Runnable" state. This state is called "Runnable"
state rather than "Running" state because the thread may not be running actually when it
is in this state. Many computers do have a single processor making it impossible to run
all the "Runnable" threads at the same time. Therefore the Java runtime system should
implement the scheduling scheme which shares the processor between all the "Runnable"
threads. For most of the purposes however, we can think of "Runnable" state as simply
"Running". When a thread is running, it is "Runnable" and is
the current thread. The instructions in the run() method are executing sequentially.
Not Runnable
A thread enters into "Not Runnable" state when one of following events occur:
When a suspend() method is called
When a sleep() method is called
When the thread uses its wait() method to wait for a condition variable
The bold line in the above example
puts myThread to sleep for 10 seconds. During these 10 seconds,
even if the processor becomes available myThread will not run. After 10 seconds are
over, myThread becomes "Runnable" again and if the processor is available it
would run.
Following statements indicates the escape route for every entrance into "Not Runnable"
state.
If the thread is put to sleep, then the specified time should elapse.
If the thread is suspended, then someone must call the resume() method.
If the thread is waiting on condition variable, whatever object owns the variable
should relinquish this by calling either notify() or notifyAll() method.
If the thread is been blocked on I/O, then the specified I/O command should get complete.
Dead
A thread can die in two different ways: either by a natural cause, or being killed (stopped).
A thread is said to die naturally when the run() method exits normally. Cosider for example,
the while loop in the run method is a finite loop, it will iterate 100 times and then stops executing.
public void run()
{
int i = 0;
while (i < 100)
{
i++;
System.out.println("i = " + i);
}
}
We can also kill a thread any time simply by calling the stop() method. This is as
shown in the code below:
The run method here creates and starts myThread then it puts the current thread to
sleep for some 10 seconds. When current thread wakes up, the bold line in the
code segment will kill myThread.
The stop() method will throw a ThreadDeath object to kill the thread. When the
thread is killed in this manner it dies asynchronously. Thread will die when it
actually receives a ThreadDeath exception.
IllegalThreadStateException
runtime system throws an IllegalThreadStateException when we call a method on a
thread and the thread's state will not allow for that method call. For example,
IllegalThreadStateException is thrown when we call a suspend() method on a thread
which is not "Runnable".
As per in the examples of threads studied so far in this chapter, when we call a
thread method which can throw an exception, you should either catch and handle the
exception, or should declare that, the calling method throws uncaught exception.
If the method isAlive() returns true then thread is started and not stopped.
Thus, if isAlive() method returns false we know that the thread is either
"New Thread" or "Dead" one . If isAlive() method returns true, you
then the thread is either "Runnable" or "Not Runnable".
Thread Priority
When a Java thread is created, it inherits the priority from the thread that created it.
We can also modify the thread's priority any time after its creation using the method
setPriority(). Threads priorities range from MIN_PRIORITY to MAX_PRIORITY
(these are the constants defined in class Thread). At any given instant of time,
when multiple threads are ready to execute, the runtime system chooses "Runnable"
thread having the highest priority for execution. Only when this thread stops, yields,
or becomes "Not Runnable" for some sort of reason, the lower priority thread start
executing. If there are two threads
having same priority waiting for CPU, the scheduler will choose them in a round-robin
fashion.
Daemon Threads
Any Java thread can be daemon thread. Daemon threads are service providers for those
threads or objects running in same process as the daemon thread is running. For example,
HotJava browser has a daemon thread, called Background Image Reader, which reads images
from the file system or network for any of the object or thread which needs an image.