Table of contents
1.
Introduction 
2.
Syntax and Key Features
2.1.
Syntax
3.
Parameters
4.
Key Features
5.
Example Code and Explanation
5.1.
Example: Basic Usage
5.2.
Java
5.3.
Explanation
6.
Frequently Asked Questions
6.1.
What is the advantage of using ThreadPoolExecutor?
6.2.
How does ThreadPoolExecutor handle idle threads?
6.3.
What is the difference between shutdown() and shutdownNow()?
7.
Conclusion
Last Updated: Aug 14, 2024
Medium

Java ThreadPoolExecutor

Author Rinki Deka
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction 

In Java programming, managing multiple threads efficiently is crucial for building high-performance applications. The ThreadPoolExecutor class is a powerful tool provided by Java to help manage a pool of worker threads. It is part of the Java Concurrency framework and allows you to execute tasks concurrently without the overhead of creating and destroying threads repeatedly.

ThreadPoolExecutor simplifies the handling of threads by reusing a fixed number of threads and managing tasks efficiently. This results in better performance and resource utilization.

Java ThreadPoolExecutor

Syntax and Key Features

Syntax

To create a ThreadPoolExecutor, use the following syntax:

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    corePoolSize,
    maximumPoolSize,
    keepAliveTime,
    timeUnit,
    workQueue
);

Parameters

  • corePoolSize: The minimum number of threads to keep in the pool, even if they are idle.
     
  • maximumPoolSize: The maximum number of threads that can be active at the same time.
     
  • keepAliveTime: The time that excess idle threads will wait for new tasks before terminating.
     
  • timeUnit: The time unit for the keepAliveTime (e.g., TimeUnit.SECONDS).
     
  • workQueue: A queue to hold tasks before they are executed.

Key Features

  1. Thread Reuse: Reuses existing threads, reducing the overhead of thread creation.
     
  2. Dynamic Thread Sizing: Can adjust the number of threads based on workload.
     
  3. Task Queuing: Manages tasks using a queue, allowing efficient task scheduling.
     
  4. Graceful Shutdown: Allows for orderly shutdown of the executor.
     
  5. Customizable: You can customize the thread pool to fit specific needs.

Example Code and Explanation

Here’s a simple example demonstrating how to use ThreadPoolExecutor.

Example: Basic Usage

  • Java

Java

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.ThreadPoolExecutor;

import java.util.concurrent.TimeUnit;

public class ThreadPoolExample {

   public static void main(String[] args) {

       // Create a ThreadPoolExecutor with 3 core threads and a maximum of 5 threads

       ThreadPoolExecutor executor = new ThreadPoolExecutor(

           3, // corePoolSize

           5, // maximumPoolSize

           60, // keepAliveTime

           TimeUnit.SECONDS, // timeUnit

           new LinkedBlockingQueue<Runnable>() // workQueue

       );

       // Submit tasks to the executor

       for (int i = 0; i < 8; i++) {

           executor.submit(new Task(i));

       }

       // Shutdown the executor

       executor.shutdown();

   }

}

class Task implements Runnable {

   private final int taskId;

   public Task(int taskId) {

       this.taskId = taskId;

   }

   @Override

   public void run() {

       System.out.println("Task " + taskId + " is running by " + Thread.currentThread().getName());

       try {

           // Simulate task processing time

           Thread.sleep(2000);

       } catch (InterruptedException e) {

           Thread.currentThread().interrupt();

       }

   }

}
You can also try this code with Online Java Compiler
Run Code

Explanation

  1. Creating the Executor:
    • ThreadPoolExecutor is created with a core pool size of 3 threads and a maximum pool size of 5.
       
    • keepAliveTime is set to 60 seconds. If a thread is idle for this time, it will be terminated.
       
    • TimeUnit.SECONDS specifies that the keepAliveTime is in seconds.
       
    • LinkedBlockingQueue<Runnable>() is used to queue tasks before they are executed.
       
  2. Submitting Tasks:
    • A loop submits 8 tasks to the executor. Each task is an instance of the Task class that implements Runnable.
       
  3. Executing Tasks:
    • Each Task prints its ID and the name of the thread executing it. The task then sleeps for 2 seconds to simulate work.
       
  4. Shutdown:
    • executor.shutdown() initiates an orderly shutdown where previously submitted tasks are executed, but no new tasks will be accepted.
       

Output

When you run this code, you will see output similar to:

Task 0 is running by pool-1-thread-1
Task 1 is running by pool-1-thread-2
Task 2 is running by pool-1-thread-3
Task 3 is running by pool-1-thread-1
Task 4 is running by pool-1-thread-2
Task 5 is running by pool-1-thread-3
Task 6 is running by pool-1-thread-1
Task 7 is running by pool-1-thread-2

Frequently Asked Questions

What is the advantage of using ThreadPoolExecutor?

ThreadPoolExecutor improves performance by reusing threads and managing task execution efficiently. It reduces the overhead associated with creating and destroying threads repeatedly. By maintaining a pool of threads, it ensures that tasks are processed quickly and resource usage is optimized.

How does ThreadPoolExecutor handle idle threads?

Idle threads are kept alive for a specified time (keepAliveTime). If there are more threads than needed, they will be terminated after this time. This helps in managing system resources efficiently by avoiding unnecessary thread creation and destruction.

What is the difference between shutdown() and shutdownNow()?

  • shutdown(): Initiates an orderly shutdown where previously submitted tasks are executed, but no new tasks are accepted. The executor waits for all tasks to complete before terminating.
  • shutdownNow(): Attempts to stop all actively executing tasks and halts the processing of waiting tasks. It returns a list of the tasks that were waiting to be executed. This method is useful for urgent shutdowns but may leave some tasks unfinished.

Conclusion

The ThreadPoolExecutor class in Java is a powerful tool for managing concurrent tasks efficiently. By reusing threads and queuing tasks, it simplifies thread management and improves application performance. Whether you're building a high-performance application or just starting with Java concurrency, understanding ThreadPoolExecutor is essential.

You can also practice coding questions commonly asked in interviews on Coding Ninjas Code360

Live masterclass