Multithreading in Java
The below article goes through explaining the concepts of Multithreading in Java and its implementation. Let’s begin the tutorial.
Concurrency nowadays has become an essential part of our lives while performing multiple tasks simultaneously. Concurrent programming consists of 2 significant concepts–Multitasking and Multithreading in Java.
Contents
- Multitasking and Multithreading
- What is Multithreading in Java?
- What is a Thread in Java?
- Life Cycle of a Thread
- Thread Class and Runnable Interface
- Creation of Thread
- Creating Multiple Threads
Also read: Object-Oriented Programming (OOPs) Concept in Java
Best-suited Java courses for you
Learn Java with these high-rated online courses
Multitasking and Multithreading
Multitasking exists between a set of processes. Here, a process can work parallel to the program or application executing. They have their own address space to store instructions. As two processes have different address spaces, no synchronization is needed to access shared resources.
On the other hand, multithreading executes multiple tasks within the same application that needs synchronization.
Let’s understand the concept of Multithreading in Java in detail.
What is Multithreading in Java?
Multithreading is the process of executing multiple tasks within the same application that occurs between threads.
A thread can be a lightweight process as it is a part of an existing process. Since a thread is a part of a process, it shares its address space. However, each thread has its own stack, program counter, and local variables. Java schedules multiple threads for these tasks.
For instance, a music application capable of playing, downloading, and searching music concurrently (at the same time). As multiple threads share the same address space of the application, synchronization is required here to ensure proper access to shared resources.
What is a Thread in Java?
Threads are like workers who have been assigned a certain task to be performed within the same application. How does it work? When a program starts, the JVM schedules the main thread to start executing it. FYI, the first thread to be created and executed inside any program is the main thread.
Also Read: Difference between JDK, JRE, and JVM
A single-threaded model begins with the main thread, and the following thread cannot initiate till the main thread ends. However, in the case of a multithreaded model, multiple tasks concurrently take place. The flow of the application starts with the main thread. However, the main thread can spawn into multiple threads.
Read: Access Modifiers in Java
Now, let’s see the life cycle of a thread to understand the concept better.
Life Cycle of a Thread
Like other processes, a thread undergoes a lifecycle from its creation to its termination.
Following are the states in a lifecycle of a thread:
- New: When a thread is created, it is said to enter a new state. However, it is not alive at this moment.
- Runnable: When a thread is ready to be assigned a processor but has not been assigned one, it is said to be in a runnable state. A thread enters a runnable state when the start() is invoked. Then it enters the alive state.
- Running: When a thread is allocated to a process, it comes in a running state. The run() method gets invoked at this state which defines the task is under process.
- Sleeping/Waiting/Blocked: A thread can switch from running to this state temporarily if it’s in sleep, wait or block. FYI, a thread can move to sleep for a time using the sleep() method. Moreover, a thread can go into a wait state and return when notified. Furthermore, a thread can go into a block state if any required resource is unavailable.
- Terminated: Once a thread completes the run() method, the execution ends, and the thread is considered terminated or dead.
The below diagram clears up the lifecycle of a thread.
Note: A thread is alive in runnable and running states only. It is neither alive in the new state nor the terminated state.
Also, Read: Data Types in Java – Primitive and Non-Primitive Data Types Explained
Thread Class and Runnable Interface
The Thread class and Runnable interface are one of the most significant entities in multithreading. They both serve various methods that aid in the creation of threads.
Below are a few of the essential constructors and methods in thread class and runnable interface.
Runnable Interface
As an interface cannot define any constructors. Therefore, the Runnable interface has constructors available.
Read: Interfaces in Java
Methods
Method Name | Description |
void run() | Capable of defining the task to be performed by a thread. |
For more information: Method Overloading in Java
Thread Class
The thread class implements the runnable interface. Therefore, it is responsible for defining the run() method.
Constructors
Constructors | Description |
Thread() | Allocates memory to the new thread object. |
Thread(Runnable target) | It allocates memory to the new thread object to run a target. |
Thread(Runnable target, String name) | It allocates memory to the new thread object to run a target with a given name. |
Thread(String name) | It allocates memory to the new thread object with a given name. |
Read: Constructors in Java
Methods
Methods | Description |
long getId() | Returns a unique identifier for a thread as a long value. |
String getName() | It returns the name of the current thread as a string value. |
int getPriority() | Returns the priority of a thread object. |
void join() | Waits for a thread to finish execution. |
Boolean isAlive() | Checks whether the given thread is alive or not. |
void run() | It invokes when the thread starts its execution. |
static Thread currentThread() | Returns a reference to the currently executing thread. |
void setName(String name) | Set the name of the given thread. |
void setPriority(int p) | Set the priority of the given thread. |
static void sleep(long milliseconds) | Suspends the execution of the current thread for the given time in milliseconds. |
void start() | Starts the execution of a particular thread. |
Read: Loops in Java
Creation of Thread
A thread behaves like a worker who works upon certain jobs. A thread always needs a target job to work upon. A job performed by the thread can be created using one of the below approaches:
- Implementing a runnable interface
- Extending thread class
Let’s see an example to understand a thread’s execution.
Example:
class job1 implements Runnable{ public void run() { System.out.println("I am a job created by implementing runnable interface"); }}class job2 extends Thread{ public void run() { System.out.println("I am a job created by extending thread class which implements runnable interface"); }}class Main { public static void main(String[] args) { job1 j1 = new job1(); Thread jobRunner = new Thread(j1); jobRunner.start(); job2 j2 = new job2(); Thread jobRunner2 = new Thread(j2); jobRunner2.start(); }}
Explanation:
Here, the threads jobRunner1 and jobRunner2 work upon the jobs instance j1 and j2 respectively.
Output:
Also, read: Strings in Java
Creating Multiple Threads
In the above section, we saw multiple threads working on different jobs. This section shows the behavior when multiple threads work on the same job.
Example:
class job1 implements Runnable{ public void run() { try { System.out.println("{This is child thread "); Thread.sleep(500); //child thread sleeping System.out.println("Running!}"); } catch (InterruptedException e) { System.out.println(e); } }} class Main { public static void main(String[] args) { job1 j1 = new job1(); //creating job1 instance Thread jobRunner = new Thread(j1); //thread1 assigned to job1 instance jobRunner.start(); Thread jobRunner2 = new Thread(j1); //thread2 assigned to job1 instance jobRunner2.start(); }}
Explanation:
The program demonstrates the creation of two threads working upon the same job named j1, an instance of job1 class. Here, we have three threads working simultaneously, main, jobRunner1, and jobRunner2. As they are working upon the same Runnable instance j1, their order of execution is not synchronized yet. Hence, results in garbled output.
Output:
Read: Implementing Array in Java.
Conclusion
I hope the above article helped you better portray multithreading in the Java concept. Multithreading is an essential and crucial topic in concurrency, synchronization, and interthread communication. We’ll cover these topics in an upcoming article. Share your queries with us at the link below, and keep learning.
For more, Read: 8 Most Important Data Structures a Programmer Must Know
This is a collection of insightful articles from domain experts in the fields of Cloud Computing, DevOps, AWS, Data Science, Machine Learning, AI, and Natural Language Processing. The range of topics caters to upski... Read Full Bio