Introduction A thread, in Java, is the execution path followed by a program. It is a lightweight sub-process, the smallest unit of processing. All Java programs have at least one thread, known as the main thread, which is created by the Java Virtual Machine (JVM), when the main() method is invoked with the main thread. Threads can be used to perform parallel tasks in the background without interrupting the main program.
Multithreading Multithreading is a Java feature that allows concurrent execution of two or more parts of a program for maximum CPU utilization. Each part of such program is called a thread. It is different from multi-processing as threads use a shared memory area. They don't allocate separate memory area so saves memory, and context-switching between the threads takes less time than process.
Life-cycle of a Thread The life cycle of the thread in java is controlled by JVM. It is broken into 5 steps as follows:
New - The thread is in new state if you create an instance of Thread class, but the code it is assigned to hasn't started execution yet. This is before the invocation of start() method.
Runnable - The thread is in runnable state after invocation of start() method. In this state, a thread be ready to run at any instant of time, but the thread scheduler has not selected it to be the running thread. A multi-threaded program allocates a fixed amount of time to each thread. Each thread runs for a short while and then pauses and relinquishes the CPU to another thread, so that other threads can get a chance to run.
Running - The thread is in running state if the thread scheduler has selected it.
Non-Runnable (Blocked) - This is the state when the thread is still alive, but is currently not eligible to run. It is either blocked by some other thread or waiting for an I/O activity to complete. Any thread in these states does not consume any CPU cycle. When a thread is waiting for I/O to complete, it’s the responsibility of the thread scheduler to reactivate and schedule the blocked/waiting thread. A thread is in the blocked state when it tries to access a section of code that is currently locked by some other thread. When the section is unlocked, the scheduler picks the blocked thread and moves it to the runnable state. A thread is in the waiting state when it waits for another thread on a condition. When this condition is fulfilled, the scheduler is notified and the waiting thread is moved to runnable state. A thread lies in timed waiting state when it calls a method with a time-out parameter. It lies in this state until the timeout is completed or until a notification is received.
Terminated - A thread is in terminated or dead state when its run() method exits. This is possible in two scenarios- the thread exited normally, the thread ran into an error and terminated abruptly. It doesn't consume CPU in this stage.
Ways to create thread There are two ways to create a thread in JAVA:
By extending Thread class - This is done by extending the java.lang.Thread class and overriding the run() method available in the Thread class. A thread begins its life inside run() method. We create an object of our new class and call start() method to start the execution of a thread. Start() invokes the run() method on the Thread object. Below is the code snippet.
class Multithreading extends Thread {
public void run() //overriding the run method
{
try {
System.out.println("Thread is running");
}
catch (Exception e) { //adding the try-catch block to handle Interruptedexception
System.out.println("Exception is caught");
}
}
}
public class ThreadList {
public static void main(String[] args)
{
Multithreading object = new Multithreading();
object.start();//starting the thread object
}
}
}
By implementing Runnable interface - This is achieved by creating a new class which implements java.lang.Runnable interface and overrides run() method. If we are using this method, the class object would not be treated as a thread object, until we explicitly create Thread class object. We are passing the object of the class that implements Runnable so that the class run() method may execute.
class Multi implements Runnable{
public void run(){
System.out.println("thread is running...");
}
public static void main(String args[]){
Multi obj =new Multi();
Thread t1 =new Thread(obj);
t1.start();
}
}
Difference between both methods The two methods of thread creation has significant differences as below:
Thread is a class whereas Runnable is a functional interface
We can achieve basic functionality of a thread by extending Thread class as it provides some inbuilt methods like yield(), interrupt() etc. that are not available in Runnable interface.
If we extend the Thread class, our class cannot extend any other class because Java doesn’t support multiple inheritance, whereas implementation of the Runnable interface allows our class to extend other base classes.
Summary In this post, we have had an introduction to threads, the lifecycle of a thread and the mechanism of thread creation. In subsequent posts, we will deep dive into the thread scheduler, thread merging, thread priority, etc.
Comentarios