Multithreading In Java

This article will teach you about multithreading and how to use it with Java. Before multithreading, we have to know some different concepts related to multithreading. Let’s first understand that in detail.

Multitasking and Multithreading

Multitasking is synonymous with process-based multitasking whereas multithreading is synonymous with thread-based multitasking.

All modern Operating Systems support multitasking, process-based multitasking is the feature by which Operating System runs two or more programs concurrently.

In multithreading, the thread is the smallest unit of code that can be dispatched by the thread scheduler.

A single program can perform two tasks using two threads. Only one thread will be executed at any given point of time given a single-processor architecture.

Process Vs Thread

  • Each process requires its own address specification but multiple threads in a program share the same address specification.
  • Context Switching from one process to another is a CPU-intensive task needing more time. But context-switching from one thread is less CPU-intensive.
  • Inter-process communication is expensive as the communication mechanism has to span separate address space but inter-thread communication is less expensive as threads in a program communicate within the same address space. 

Uses of Multithreading

  • Use to develop client-server applications
  • Use to develop gaming application
  • Use to develop animation based Java application
  • To improve the performance of the application and to use the CPU time in optimum way use threads.

The Thread Class

Java’s multithreading feature is built into the thread class. The thread class has two primary thread control methods; starts() and run(). 

start() method starts a thread execution, run() method executes business logic written inside the run method and is the entry point for the thread.

The thread dies when the run() method terminates. We can never call run() explicitly. This start() call automatically initiates a call to the threads run() method.

Different stages of a Thread / Thread lifecycle

  • When we create a thread instance, the thread is considered to be in a new state. In this state, the thread is considered to be NULL and VOID.
  • When we invoke a run() method to the thread instance, the thread appears in a runnable state.
  • When we invoke a wait() / sleep() to a runnable thread it goes to a not runnable state,

Sleep(args) takes milliseconds as args.

  • Dead state when the thread completes its execution. In other words, when a thread is terminated it enters a dead state.

The Main Thread

Each and every executable java program at least contains one thread i.e main thread.

The main thread is a predefined thread in java, always the main method(public static void main(String[] args)) is executed by the main thread.

After termination, all child threads can be accessed by obtaining a reference to the thread using a public, static method in the Thread class called currentthread().

Example

public class ThreadInfo() {
    public static void main(String[] args) {
        Thread t = Thread.currentThread();
        System.out.println("Current Thread : " + t);
        t.setName("Demo Thread");
        System.out.println("New name of the thread : " + t);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            System.out.println("Main Thread Interrupted");
        }
    }
}

Output

Current Thread: Thread[main, 5, main]
The new name of the thread: Thread[DemoThread, 5, main]
 

Creating Thread

We can create threads by extending the thread class or by implementing a Runnable interface.

A thread can be created by instantiating an object of type thread. The code which will run as a thread must be written under run() method. Just like any other java code, we can write any program under Thread.run() method, this thread after run() returns or terminates.

Creating Thread: Implementing Runnable

Create a class implementing Runnable interface. The Runnable interface has only one method called run() to implement. The code which we want to execute in a thread must be written inside the run() method. 

We can’t invoke a method by implementing the Runnable interface directly. To invoke a thread method, we need to create an object of type Thread from the object of that class. First, we need to invoke the object of type Thread from the object of the thread class. The thread will end when run() returns or terminates.

Example

public class RunnableDemo {
    public static void main(String[] args) {
        System.out.println("From main() : " + Thread.currentThread().getName());
        System.out.println("Creating Runnable Instance...");
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("From run() : " + Thread.currentThread().getName());
            }
        };
        System.out.println("Creating a Thread Instance...");
        Thread thread = new Thread(runnable);
        System.out.println("Launching a Thread...");
        thread.start();
    }
}

Output

From main() : main
Creating Runnable Instance...
Creating a Thread Instance...
Launching a Thread...
From run() : Thread-0
 

Creating Thread: Extend Thread Class

We can also create threads by extending the superclass Thread Class.

Instantiate the class that extends Thread class and this class must override the run() method. To invoke a thread method, we need to create an object of type Thread from the object of that class. We must call the start() on this thread.

start() method in turn calls the thread run() method.

public class MyThread extends Thread {
    public void run() {
        System.out.println("Thread running");
    }
    public static void main(String args[]) {
        MyThread mt = new MyThread();
        mt.start();
    }
}

Output

Thread running

While extending the Thread class we must override the run() method and then start() and run the thread. 

What if we call the run() method directly the thread won’t allocate a new stack and it will start running in the current stack, this is the stack of the main thread. Hence the concept of multithreading will be ruined.

Which is an efficient Runnable interface or Thread class?

According to the experts pertaining to hierarchy, classes should be extended only when they are enhanced or modified in some way i.e java doesn’t support multiple inheritances; only one class can be extended at a time within a class. So if the aim is to define an entry point for the thread by overriding the run() method & not override any of the Thread class other methods, it is recommended to implement the Runnable interface.

Summary

Thus, coming towards the end of this article, the basic aim is to know about multithreading, its uses, and how it will be helpful for developers.

What did we learn?

  • Multitasking and Multithreading
  • Process Vs Thread 
  • Uses of Multithreading
  • The Thread Class
  • Life Cycle of the Thread
  • The Main Thread
  • Creating Thread by Thread Class
  • Creating Thread by Runnable Interface
  • When to use Runnable Interface and Thread Class