In Java, threads are objects and can be created in two ways:
1. by extending the class Thread
2. by implementing the interface Runnable
In the first approach, a user-specified thread class is created by extending the class Thread and overriding its run () method. In the second approach, a thread is created by implementing the Runnable interface and overriding its run () method. In both approaches the run () method has to be overridden. Usually, the code that is to be executed by a thread is written in its run () method. The thread terminates when its run () method returns.
In Java, methods and variables are inherited by a child class from a parent class by extending the parent. By extending the class Thread, however, one can only extend or inherit from a single parent class (in this case, the class Thread is the parent class). This limitation of using extends within Java can be overcome by implementing interfaces. This is the most common way to create threads. A thread that has been created can create and start other threads.
We’ll be covering the following topics in this tutorial:
Creating a new thread extending Thread
The first method of creating a thread is simply by extending the Thread class. The Thread class is defined in the package java.lang. The class that inherits overrides the run () method of the parent
Thread for its implementation. This is done as shown in the code fragment given below. By its side a representation of the inheritance that is being implemented.
A thread can be started by applying the start () method on the thread object. The following code segment creates an object of the thread class and starts the thread object.
class Start Threadclass
{
public static void main (String args [ ])
{
……..
……..
SampleThread st = new SampleThread ();
st.start ();
…….
}
}
Here, the thread object st of the thread class SampleThread is created as
SampleThread st = new SampleThread ();
To start the thread object st, the start () method can be applied on this object as
st.start ();
When the above statement is executed, the run () method of the SampleThread class is invoked. The start () method implicitly calls the run () method. Note that the run () method can never be called directly.
Look at Program which creates a thread class ThreadExample which extends the class
Thread and overrides the method Thread.run (). The run () method of this program is where all the work of the ThreadExample class thread is done. This instance of the class is created in the ExampleT class. The start () method on this instance starts the new thread. The child thread prints the values from 0 to 5.
Program Using extends to write a single-thread program.
import java.lang.*;
class ThreadExample extends Thread
{
public ThreadExample (String name)
{
super (name);
}
public void run ()
{
System.out.println (Thread.currentThread ());
For (int i=0; i<=5; i++)
System.out.println (i);
}
}
public class ExampleT
{
public static void main (String args [ ])
{
ThreadExample t = new ThreadExample (“First”);
t.start ( );
System.out.println (”This is:” + Thread.currentThread ());
}
}
The output of Program is as follows:
This is: Thread [main, 5, main]
Thread [First, 5, main]
0
1
2
3
4
5
The first line of the output shows the name of the thread (main), the priority of the thread (5) and the name of the ThreadGroup (main). In the second line, First, 5 and main are the name, priority and name of the ThreadGroup of the child thread.
The created thread does not automatically start running. To run a thread, the class that creates it must call the method start () of the Thread. The start () method then calls the run () method. When applying the start () method on a thread object, a new flow of control starts processing the program. The start () method can be invoked either from the constructor or any method in which the thread is created. Figure 6.1. shows the running of both main and child threads.
In Program the main method creates an object a thread class ThreadExample. After
executing the statement
ThreadExample t = new ThreadExample (“First”);
Thread object t is in the newborn state of the thread life cycle. When a thread is in newborn state, it does not hold any system resource and the thread object is said to be empty. A thread can be started only when it is in the newborn state by calling the start () method. Calling any method other than the start () method will cause an exception IilegalThreadStateException. The start () method creates the necessary system resources to run the thread, schedules the thread to run, and calls the thread’s run () method. The thread object t calls the start () method of the ThreadExample class. Thread object’s run method is defined in the ThreadExample class. After execution of t.start () statement, the thread is in the runnable state. Henceforth, both the thread object as well as main thread are in the runnable state.
Every Java applet or application is multithreaded. For instance, main itself is a thread created by extending the Thread class.
Creating a thread implementing Runnable interface
The interface Runnable is defined in the java.lang package. It has a single method-run ().
public interface Runnable
{
public abstract void run ();
}
If we want multithreading to be supported in a class that is already derived from a class other than Thread, we must implement the Runnable interface in that class.
The majority of classes created that need to be run as a thread will implement Runnable since they may be extending some other functionality from another class. Whenever the class defining run () method needs to be the sub-class of classes other than Thread, using Runnable interface is the best way of creating threads. The syntax and the inheritance structure are given below.
public class SampleThread extends
The class Thread itself implements the Runnable interface (package java.lang) as expressed in the class header:
public class Thread extends Object implements Runnable
As the Thread class implements Runnable interface, the code that controls the thread is placed in the run () method. In order to create a new thread with Runnable interface, we need to instantiate the Thread class. This thread class will have the following constructors:
public Thread (Runnable obj);
public Thread (Runnable obj, String threadname);
public Thread (ThreadGroup tg, Runnable obj, String threadname);
Here, obj is the object of the class which implements the Runnable interface, threadname is the name given to the thread and tg is the name of the ThreadGroup.
Program illustrates the creation of threads using Runnable interface.
Program Using Runnable interface to write a single-thread program.
class ThreadExample implements Runnable
{
Thread t;
public ThreadExample (String threadname)
{
t = new Thread (this, threadname);
}
public void run ()
{
System.out.println (Thread.currentThread () );
for (int i =0; i <=5; i++)
System.out.println (i);
}
}
public class ExampleT2
{
public static void main (String args [ ])
{
ThreadExample obj = new ThreadExample (“First”);
Obj.t.start ( );
System.out.println (“This is:” + Thread.currentThread ());
}
}
The output of Program is as shown below.
This is: Thread [main, 5, main]
Thread [First, 5, main]
0
1
2
3
4
5
In Program, in place of the Thread class constructor parameters we passed this and First. Here this refers to the ThreadExample class on which the thread is created. Here, the abstract run () method is defined in the Runnable interface and is being implemented.
By implementing Runnable, there is greater flexibility in the creation of the class
ThreadExample.
In the above example, the opportunity to extend the ThreadExample class, if needed, still
exists.
The method of extending the Thread class is good only if the class executed as a thread does not ever need to be extended from another class.
Stopping threads: the join () method
Generally, when the execution of a program starts the thread main is started first. Child threads are started after the main thread. So it is unusual to stop the main thread before the child threads. The main thread should wait until all child threads are stopped. The join () method can be used to achieve this. The syntax of this method is as follows:
final void join () throws InterruptedException
The join () method waits until the thread on which it is called terminates. That is, the calling thread waits until the specified thread joins it. A thread (either main thread or child threads) calls a join () method when it must wait for another thread to complete its task. When the join () method is called, the current thread will simply wait until the thread it is joining with either completes its task or is not alive. A thread can be in the not alive state due to anyone of the following:
• the thread has not yet started,
• stopped by another thread,
• completion of the thread itself
The following is a simple code that uses the join () method:
try
{
t1.join ()
t2.join ();
t3.join ();
}
catch (interupptedException e)
{
}
Here t(1), t(2), t(3) are the three child threads of the main thread which are to be terminated before the main thread terminates. If we check the isAlive () on these child threads after the join () method, it will return false.
There is another form of the join () method, which has a single parameter that specifies how much time the thread has to wait. This is the following:
final void join (long milliseconds) throws InterruptedException
Naming a thread
By default, each thread has a name. Java provides a Thread constructor to set a name to a thread. The name can be passed as a string parameter to this constructor, in the following manner:
Thread t = new Thread (“First”);
Thread t = new Thread (Runnable r, “SampleThread”);
The setName method of the Thread class can also be used to set the name of the thread, in the following manner:
void setName (String threadname);