What is multithreading in Java?

Multithreading or concurrent processing within an application refers to completing many tasks at the same time. Concurrent processing is done in the Java programming language by executing several threads in parallel.

Thread

A thread is a small operation that serves as the foundation for CPU use. A thread composes a thread id, a counter for the program known as program counter (PC), a stack, and a register set.

The smallest unit of processing is a thread, which is a lightweight sub-process. Multitasking is accomplished using multiprocessing and multithreading.

Below is a diagram explaining what a thread is.

A simple thread
A simple thread

From the diagram above, AB is a Thread created. The beginning stage is where Thread AB instantiated. It (Thread AB) then moves to the execution stage. At this point, the thread is running. The Thread AB is closed/ended (referred to as destroy) at the end-stage.

The above diagram clearly shows an example of a thread which is a task AB, which has the beginning stage, then moves to the execution stage of commands or whatever is to be performed. It then concludes by reaching the End stage, which indicates the completion of the thread or task.

What is multithreading?

Multithreading simply denotes the process in which several threads are running at the same time in a computer program.

This can illustrated as an individual who is answering a call, walking down the stairs and at the same time looking at his/her front all at the same time. Looking at this example, it is obvious that each of the tasks being carried out can also be done independently, but were all combined to be done at a time, which could be linked to multithreading. Below is an image which depicts the multithreading process in a computer which comprises of several threads being run at a time.

Multithreading Illustration
Multithreading Illustration

Because threads share memory, we employ multithreading rather than multiprocessing. Threads conserve memory by not allocating a distinct memory region, and context-switching between threads takes less time than the process. Multithreading in Java is primarily utilized in gaming, animation, and other similar applications.

There are five stages for a thread to pass through. The thread life cycle in Java has only four states:

  • Created
  • Runnable
  • Non-runnable
  • Terminated

According to Sun Oracleowners of Java, there is no such thing as a running state.

However, to help you comprehend the threads, we have broken them down into five states.

JVM manages the thread life cycle in Java. The following are the states of a Java thread:

Thread life circle

The life circle of a thread comprises of the following distinct stages:

The new stage:
At this stage, an instance of a new thread is created and the which precedes the calling of the start() method.

The runnable stage:
At this stage, which is the second stage, the created thread in the first stage initializes the start() method but awaits the thread scheduler to take it to the runnable stage. It has been prepared for running, but not yet placed on the runnable stage yet.

The running stage:
Like the name implies, this is when the scheduler calls the thread to commence running.

The non-runnable stage (blocked stage):
Also referred to as the blocked stage, this is the state whereby the thread is still active/alive but is being paused or not currently running at that point in time due to non-availability of resources at its disposal being used by other threads or a deadlock.

  • Block stage occurs when an I/O or resources is being used by another thread, say Thread A, and the thread which is at this stage, say Thread B, is waiting for the thread to be released by Thread A to be able to enter the runnable stage.

  • Deadlock happens when a thread keeps waiting for another thread that is in turn waiting for another which might never be released.

The terminated state:
At this point, the thread is terminated or dead state, which implies that the run() method has been exited.

The image below describes the stages mentioned above for a clearer view.

Thread Life Cycle
Thread Life Cycle

Java thread methods

There are several methods being defined by our thread Java class that are used in managing our program threads. The table below gives a summary of the major methods used by our threads and the meaning or the task performed by such methods.

Thread Class Methods
Thread Class Methods

Java main thread

Let’s look at how to construct and manage threads using the Thread class and Runnable interfaces, starting with the primary Java thread that all Java programs have, which is the main thread.

What is the significance of the main thread?

  • The main thread affects every other child thread that will be created.

  • The main thread is the thread that runs finally (at last) and can shutdown actions and other threads that are running.

  • It is being created automatically when a program is created and run.

Thread creation

In Java programming language, threads can be created in several ways. The simplest way is to create a single thread by implementing the Runnable interface or by extending the Thread class from the user class.

To buttress the types of thread implementation, we will be looking at two types of thread implementation and code examples for each.

1. Implementing the Runnable class

class ThreadExampleRunnable implements Runnable{
public static void main(String[] args) {
ThreadExampleRunnable Thr1 = new ThreadExampleRunnable();
Thread th1 = new Thread(Thr1);
th1.start();
}
public void run(){
System.out.println("Thread is running by runnable interface implementation...");
}
}

In the case of using the runnable interface as shown above, our thread class (i.e., ThreadExampleRunnable) is created and the Runnable interface is implemented in the class. The class then invokes the run method within which our thread action is called.

The class (i.e. ThreadExampleRunnable) is called in our main class for execution by instantiating the class object and executing it by calling the start method on it.

2. Extending to the Thread class

class ThreadExampleExtendingThreadClass extends Thread{
public void run(){
System.out.println("Thread is running by the extending to the Thread class...");
}
public static void main(String args[]){
ThreadExampleExtendingThreadClass thread1 = new ThreadExampleExtendingThreadClass();
thread1.start();
}
}

For this method of creation of thread, just like in the first case, our class (ThreadExampleExtendingThreadClass) is created and is extended to the Thread class. The run method is therefore invoked within the class and the task is defined within the method. The thread is called within the main method by instantiating the class object and executing it by calling the start method on it.

Which strategy should I use for thread creation?

Although we can establish a new Thread with either strategy and they both operate properly, the first approach (which is the implementation of the Runnable interface) is always preferred and suggested over the use of extending to the Thread class, based on these few reasons:

  • Multi-inheritance is not allowed in the Java language so far, hereby if used for the creation of threads, the class loses its ability to extend to any other class while it has the runnable option to go with, which defeats the OOP option of subclassing and inheritance usage.

  • According to OOP principles, a sub class provides more specialised functionality in the parent-child hierarchy. This principle is violated when the Thread class is extended to provide implementation for new threads by overriding run().

The following are a few of the most well-known multithreading advantages:

  • Improved performance is the result of reduced development time. Program coding has been cut and simplified.

  • The GUI’s responsiveness has been improved. Tasks are carried out in a parallelized and concurrent manner.

  • You can make greater use of cache storage by better utilizing resources.

  • The expense of maintenance is reduced.

  • CPU resources are used more efficiently. Multithreading offers several benefits, but it also has some disadvantages.

  • Better use of CPU resource.

Multithreading does not only provide you with benefits. It has its disadvantages too.

Let’s also consider some downsides of multithreading:

  • Processes of complex debugging and testing.
  • Context switching overhead.
  • Deadlocks have a higher chance of occurring.
  • The amount of difficulty in writing a program has risen.

This is just an overview of what multithreading provides users. However, other concepts of multithreading exist that are beyond this shot.

Free Resources

Copyright ©2024 Educative, Inc. All rights reserved