Java Thread Creation
Java provides the two ways to create a Thread:
- Implementing the Runnable interface.
- Extending the Thread class.
Implementing Runnable interface
The easiest way of creating a thread is to make a class that implements the Runnable interface. The runnable interface represents a unit of executable code. We can create a thread on the object which implements Runnable. A class only implements a single method called run() if it implements the Runnable interface.
We will define the code in the run method of the Runnable interface that constitutes the new thread. The run() can call other methods of the class, can use other classes, and declare variables. The run() establishes the entry point for the execution of the thread within your program. The thread will end when run() finishes.
We can instantiate an object of type Thread in which a class that implements Runnable is passed so that we can start the new thread. Thread has a constructor that we will use to start the run method of the Thread class.
Syntax:
Thread(Runnable r1, String tname)
In this constructor, r1 is an instance of a class that implements the Runnable interface, and tname is the name of the new thread. When the new thread is created, it will start running when you call its start() method, which is declared within Thread.
Steps for creating a new thread using Runnable:
Step1: Create a Runnable implemented class and implements the run() method.
Step2: Instantiate Thread class and pass the Runnable implemented class to the Thread, Thread has a constructor which accepts Runnable implementer instance.
Step3: Invoke start() of Thread instance, start() internally calls run() of the implemented class. By invoking start() creates a new Thread, which executes the code written in the run().
Example1: Creating the thread using the Runnable interface.
class Thread2 implements Runnable{ Thread t; Thread2(){ //create a new,second thread. t=new Thread(this, "Shifa-thread"); System.out.println("The child thread is the :"+t); t.start();//we are starting the thread. } //this is the entry point for execution of the second thread. public void run() { try { for(int i1=5;i1>0;i1--) { System.out.println("child thread:"+i1); Thread.sleep(500); } }catch(InterruptedException ex) { ex.printStackTrace(); } System.out.println("The exiting child thread is the"); } } public class Multithread{ public static void main(String[] args) { new Thread2();//create a new thread. try { for(int i=5;i>0;i--) { System.out.println("Main thread:"+i); Thread.sleep(1000); } }catch(InterruptedException e) { e.printStackTrace(); System.out.println("Main thread interrupted"); } System.out.println("Main thread exiting"); } }
Output:
Explanation:
In the Thread2 class ‘s constructor, a new Thread object is created by the following statement:
t=new Thread(this, "Shifa thread");
when start()method calls ,this cause the child thread’s for loop to begin. When the main resume its execution it enters into the loop. Then both sharing the cpu until their loops finish.
Creating the thread by extending the Thread class
A thread class can also make by extending the predefined Thread class, and then to instantiate that class. The entry point run() method for the new thread, must be overridden in the extended class. Here is the preceding program was rewritten to extend Thread.
Steps to create a new thread using Thread class:
Step1: Create a Thread extended class and overriding run() method of the Thread class according to your requirements.
Step2: Instantiate Thread extended class.
Step3: Invoke start() of Thread class through the instance of the Thread extended class, start() internally calls run() method which overrides in the user class. The whole activities of the thread which is defined in the run() executes.
Example1: Create the thread using the Thread class.
class Thread3 extends Thread{ Thread3(){ super("Demo Thread"); System.out.println("child thread:"+this); start();//start the thread. This is equivalent to this.start(). } //The run() is the entry point for the second thread. public void run() { try { for(int i1=5;i1>0;i1--) { System.out.println("child thread:"+i1); Thread.sleep(500); } } catch(InterruptedException ex) { ex.printStackTrace(); } } } public class Multithread { public static void main(String args[]) { new Thread3();//create a new thread. try { for(int i=5;i>0;i--) { System.out.println("Main thread:"+i); Thread.sleep(1000); } }catch(InterruptedException e) { System.out.println("Main thread interrupted"); } System.out.println("Main thread exiting"); } }
Output:
Explanation:
The thread of the child is created by creating the object of Thread3, which is derived from Thread. The super() inside Thread3 invokes the parent Thread constructor e.g., public Thread(String tName).Here, tName specifies the name of the thread.
Example2: Creating multiple threads and using Thread class having isAlive() and join() method:
It is a program to ensure that the main thread is the last to stop.
class NewThread extends Thread{ String name;// name of the thread. Thread t; NewThread(String threadname){ name=threadname; System.out.println("new thread:"+name); } //This is the entry point for the threads. public void run() { try { for(int i=3;i>0;i--) { System.out.println(name+":"+i); Thread.sleep(1000); } }catch(InterruptedException e) { System.out.println(name+"interrupted"); } System.out.println(name+"exiting"); } } public class Multithread { public static void main(String args[]) { NewThread ob1= new NewThread("one");//start threads NewThread ob2= new NewThread("Two"); NewThread ob3= new NewThread("Three"); ob1.start(); ob2.start(); ob3.start(); System.out.println("Thread one is alive:"+ob1.isAlive()); System.out.println("Thread two is alive:"+ob2.isAlive()); System.out.println("Thread three is alive:"+ob3.isAlive()); System.out.println("Main thread exiting"); //wait for threads to finish. try {//wait for the threads to finish. System.out.println("waiting for threads to finish"); ob1.join(); ob2.join(); ob3.join(); }catch(InterruptedException e) { System.out.println("Main thread Interrupted"); } System.out.println("Thread one is alive"+ob1.isAlive()); System.out.println("Thread two is alive"+ ob2.isAlive()); System.out.println("thread three is alive"+ob3.isAlive()); System.out.println("main thread exiting."); } }
Output:
Explanation:
If we want the main thread to finish last. The program is accomplished by calling sleep() within main(), but how can one thread know when another thread has ended its execution. We can call isAlive() on the thread to determine whether a thread has finished or not. If the thread upon which the isAlive() method is called is still running it returns true. It returns false if the thread is not running.
The join() method causes to waits the other thread until the thread on which it is called terminates.
Difference between the Thread class and Runnable interface
Following are some key differences between Thread class and Runnable interface:
1. There is an additional method that has to override in the class, i.e., they consume excess or indirect memory, computation time, or other resources.
2. In Java, we can only extend one class, and therefore if we extend Thread class, then we will not be able to extend any other class. That is why we should implement the Runnable interface to create a thread.
3. Runnable makes the code more flexible as, if we are extending a thread, then our code will only be in a thread whereas, in case of runnable, one can pass it in various executor services, or pass it to the single-threaded environment.
4. Maintenance of the code is easy if we implement the Runnable interface.