- A single-thread application executes tasks sequentially, one after another, where only one thread performs operations at a time.
- A multi-threaded application allows multiple threads to run concurrently, enabling tasks to be executed simultaneously. This improves efficiency and responsiveness, especially for tasks that can operate independently.
What is multithreading in Java?
Multithreading in Java refers to concurrently executing two or more threads (lightweight subprocesses) within a single program. This feature allows Java applications to perform multiple tasks simultaneously, improving efficiency and performance.
The primary purpose of multithreading is to maximize CPU utilization and enhance application responsiveness, especially in scenarios where tasks are independent and can be executed in parallel. Suppose a web server handles multiple client requests. Each client request can be processed by a separate thread, enabling the server to serve multiple clients concurrently without significant delays.
So the question in our mind might come, what is multitasking and threads? Let's explore first this concept in-depth below:
What is multitasking?
Multitasking refers to the ability of an operating system to execute multiple tasks (processes or threads) simultaneously. Multitasking can be categorized into two types:
1. Process-based multitasking
In process-based multitasking, multiple processes run concurrently. Each process has its own memory space. Thises process-based multitasking, is used for executing independent programs, such as running a browser and a word processor simultaneously.
For example: Watching a video on a media player while downloading files using a download manager.
2. Thread-based multitasking
In thread-based multitasking, multiple threads of a single process execute concurrently. Threads share the same memory space, making this approach more efficient for tasks that require interaction or shared resources.
For example: In a word processor, one thread can check spelling while another saves the document in the background.
So the question again arises what is thread? Let's discuss threads in Java:
What is a thread in Java?
A thread in Java is the smallest unit of a program that can execute independently. Threads in Java are like small, independent tasks within a program. You can create and control them using the Thread class or the Runnable interface. Threads allow for parallel execution of tasks, making programs more responsive and efficient.
For example: In a gaming application, a thread can handle rendering graphics while another manages user input.
Now that we understand what threads are, letβs explore their lifecycle to see how they function in a program.
Lifecycle of a thread in Java
The lifecycle of a thread in Java consists of the following states:
1. New
Definition: A thread is created using the
Threadclass but has not yet started.Syntax:
Thread t = new Thread();Purpose: Prepares the thread for execution.
2. Runnable
Definition: A thread is ready to run and waiting for CPU time.
Syntax:
t.start();Purpose: Marks the thread as eligible for execution.
3. Running
Definition: The thread is actively executing its task.
Purpose: The thread is assigned CPU time for execution.
4. Blocked/Waiting
Definition: The thread is temporarily paused, waiting for a resource or signal.
Purpose: Ensures resources are allocated safely without conflicts.
5. Terminated
Definition: The thread completes its task or is manually stopped.
Syntax: Thread execution ends naturally or using
t.stop();Purpose: Frees up system resources.
What is multithreading in Java?
Multithreading in Java is a technique that allows multiple threads to run concurrently within a single program. Multithreading enhances performance and responsiveness by executing independent tasks simultaneously. For example, A video streaming application where one thread handles buffering, another manages user input, and another updates the interface.
Methods of multithreading in Java
Java provides two primary ways to create and manage threads:
1. Using the thread class
How it works: Extend the
Threadclass and override itsrun()method.Code example:
class MyThread extends Thread {public void run() {System.out.println("Thread is running");}}public class main {public static void main(String[] args) {MyThread t = new MyThread();t.start();}}
2. Using the runnable interface
How it works: Implement the
Runnableinterface and pass it to aThreadobject.Code example:
class MyRunnable implements Runnable {public void run() {System.out.println("Thread is running");}}public class main {public static void main(String[] args) {Thread t = new Thread(new MyRunnable());t.start();}}
Example of multithreading in Java
Let's discuss the example of multithreading where we will show how to create two tasks that run concurrently. Task1 extends the Thread class, and Task2 implements the Runnable interface. Both tasks print their respective messages in a loop. These threads are started using the start() method to execute simultaneously.
Here is a practical example demonstrating multithreading:
// Task1 class extends the Thread class to create a threadclass Task1 extends Thread {// The run() method defines the task this thread will executepublic void run() {// Loop to print Task1 messages five timesfor (int i = 0; i < 5; i++) {System.out.println("Task 1 - " + i); // Print the current iteration for Task1}}}// Task2 class implements Runnable to define a thread's taskclass Task2 implements Runnable {// The run() method defines the task for this threadpublic void run() {// Loop to print Task2 messages five timesfor (int i = 0; i < 5; i++) {System.out.println("Task 2 - " + i); // Print the current iteration for Task2}}}// Main class to test the threadspublic class main {public static void main(String[] args) {// Create an instance of Task1, which extends ThreadTask1 t1 = new Task1();// Create an instance of Task2 and pass it to a Thread objectThread t2 = new Thread(new Task2());// Start the first thread (Task1)t1.start();// Start the second thread (Task2)t2.start();}}
Explanation:
Line 2β10: Task1 class extends the Thread class, allowing it to directly represent a thread. public void run() method is overridden to define the task for Task1. The JVM calls this method when the thread starts. A loop iterates five times, printing the current iteration with "Task 1" as a prefix.
Line 13β21: Task2 class implements the Runnable interface, which is another way to define a thread's task. new Thread(new Task2()). A Task2 instance is wrapped in a Thread object since Runnable must be passed to a Thread for execution.
Line 33β36: t1.start() and t2.start() threads are started using the start() method, invoking their run() methods and executing them concurrently.
Modify the code to create a new task class (e.g., Task3) using either Thread or Runnable, and print custom messages alongside Task1 and Task2 to observe concurrent execution.
Multiprocessing vs. multithreading in Java
Multiprocessing | Multithreading |
Running multiple processes concurrently. | Running multiple threads concurrently. |
Requires more memory (separate memory). | Shares memory within the same process. |
Suitable for CPU-intensive tasks. | Lower overhead for context switching. |
Higher overhead for context switching. | Lower overhead for context switching. |
Key takeaways
Excessive threads can lead to resource contention and overhead due to context switching. Use thread pools to manage threads effectively.
For shared data between threads, prefer thread-safe data structures like
ConcurrentHashMapor synchronized blocks to avoid race conditions.Use synchronization judiciously to avoid thread deadlocks and performance bottlenecks. Only synchronize critical sections of code.
Use Java's
ExecutorServiceand other classes from thejava.util.concurrentpackage for better thread management.When a thread is interrupted, ensure it gracefully stops or cleans up resources instead of abruptly terminating.
Implement the
Runnableinterface whenever possible as it allows the class to inherit from another class, improving flexibility.Reduce thread-blocking calls like
Thread.sleep()or I/O operations within critical threads to prevent slowing down the application.
Unlock your Java potential and take control of your coding journey! Start learning Java today to explore other than multithreading, build Java-based applications, and become a Java developer now!
Frequently asked questions
Havenβt found what you were looking for? Contact Us