Day 11: Multithreading in Java

Day 11: Multithreading in Java


3 min read

Multithreading refers to the ability of a program to execute multiple threads (sequences of instructions) concurrently. Java provides several ways to create threads and execute them concurrently.

Threads vs Processes

  • Threads share the same memory and resources while processes have separate memory and resources.

  • Creating new processes is expensive but creating threads is cheap.

Creating Threads

There are two ways to create threads in Java:

  1. By extending the Thread class

  2. By implementing the Runnable interface

Extending Thread Class:

public class MyThread extends Thread {
   public void run() {
     // Thread execution code   

MyThread t = new MyThread();
t.start(); // Starts the thread execution

Implementing Runnable:

class MyRunnable implements Runnable {
   public void run() {
     // Thread execution code   

MyRunnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();  // Starts the thread execution

Advantages of using Runnable over extending Thread:

  • It follows OOP principles (favor composition over inheritance)

  • A class can implement multiple interfaces but extend only one class

Thread Life Cycle

A thread goes through the following states:

  • New

  • Runnable

  • Running

  • Blocked

  • Waiting

  • Terminated

Available methods on Thread class:

  • start() - Starts the thread's execution

  • run() - Contains the code representing the thread's activity

  • yield() - Pauses the currently running thread

  • join() - Waits for a thread to terminate

  • sleep(millis) - Pauses the current thread for the given time

  • getName() - Returns the name of this thread

  • setName() - Sets the name of this thread

Joining Threads

The join() method waits for a thread to terminate:

t.join(); // Waits for thread t to terminate

A Thread can join itself:

public void run() {
  // ...    
  join(); // Waits for this thread to terminate

Thread Synchronization

When multiple threads access shared data concurrently, some form of synchronization is required to avoid race conditions and inconsistent data.

Synchronized Methods:

public synchronized void method() {
   // Only one thread can execute  
   // this method at a time

Synchronized Blocks:

public void method() {
   synchronized(this) {  
     // Only one thread can execute  
     // this synchronized block  
     // at a time

Here, this refers to the current object and acts as the lock.

Thread Pool

A thread pool contains pre-instantiated threads that are used to execute submitted tasks. It avoids the overhead of creating new threads for each task.

Java provides the ExecutorService interface to implement the thread pool:

ExecutorService pool = Executors.newFixedThreadPool(5); 
pool.submit(new RunnableTask()); 

This creates a thread pool with 5 threads and submits a task to it. Finally, we shut down the pool when tasks are complete.

Did you find this article valuable?

Support Laxman Rai by becoming a sponsor. Any amount is appreciated!