Java Executors Utility Class
The Executors class provides factory methods to create different types of thread pools and executors, which are commonly used in backend development.
Overview
Section titled “Overview”The Executors class offers several factory methods to create thread pools with different characteristics:
newSingleThreadExecutor(): Creates a single-threaded executornewFixedThreadPool(int nThreads): Creates a thread pool with a fixed number of threadsnewCachedThreadPool(): Creates a thread pool that creates new threads as needednewScheduledThreadPool(int corePoolSize): Creates a thread pool for scheduling tasksnewWorkStealingPool(): Creates a thread pool that uses work-stealing for load balancing
Types of Executors
Section titled “Types of Executors”1. Single-Thread Executor
Section titled “1. Single-Thread Executor”A single-threaded executor ensures that tasks are executed sequentially in a single thread.
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;
public class SingleThreadExecutorExample { public static void main(String[] args) { ExecutorService executor = Executors.newSingleThreadExecutor();
for (int i = 1; i <= 5; i++) { int taskId = i; executor.submit(() -> { System.out.println("Executing Task " + taskId + " in thread: " + Thread.currentThread().getName()); }); }
executor.shutdown(); }}2. Fixed-Thread Pool
Section titled “2. Fixed-Thread Pool”A fixed-thread pool creates a pool with a fixed number of threads. Tasks are queued if all threads are busy.
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;
public class FixedThreadPoolExample { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 1; i <= 10; i++) { int taskId = i; executor.submit(() -> { System.out.println("Executing Task " + taskId + " in thread: " + Thread.currentThread().getName()); }); }
executor.shutdown(); }}3. Cached-Thread Pool
Section titled “3. Cached-Thread Pool”A cached-thread pool creates new threads as needed and reuses previously created threads when available. It is suitable for short-lived tasks.
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;
public class CachedThreadPoolExample { public static void main(String[] args) { ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 1; i <= 10; i++) { int taskId = i; executor.submit(() -> { System.out.println("Executing Task " + taskId + " in thread: " + Thread.currentThread().getName()); }); }
executor.shutdown(); }}4. Scheduled Thread Pool
Section titled “4. Scheduled Thread Pool”A scheduled thread pool is used to schedule tasks to run after a delay or periodically.
import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;
public class ScheduledThreadPoolExample { public static void main(String[] args) { ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
// Schedule a task to run after a delay scheduler.schedule(() -> { System.out.println("Task executed after 3 seconds delay in thread: " + Thread.currentThread().getName()); }, 3, TimeUnit.SECONDS);
// Schedule a task to run periodically scheduler.scheduleAtFixedRate(() -> { System.out.println("Periodic task executed in thread: " + Thread.currentThread().getName()); }, 1, 2, TimeUnit.SECONDS);
// Schedule a task with a fixed delay between executions scheduler.scheduleWithFixedDelay(() -> { System.out.println("Task executed with fixed delay in thread: " + Thread.currentThread().getName()); }, 1, 2, TimeUnit.SECONDS); }}5. Work-Stealing Pool
Section titled “5. Work-Stealing Pool”A work-stealing pool is introduced in Java 8. It creates a pool of threads that dynamically balance the workload among themselves.
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;
public class WorkStealingPoolExample { public static void main(String[] args) { ExecutorService executor = Executors.newWorkStealingPool();
for (int i = 1; i <= 10; i++) { int taskId = i; executor.submit(() -> { System.out.println("Executing Task " + taskId + " in thread: " + Thread.currentThread().getName()); }); }
// Since work-stealing pool uses daemon threads, we need to wait for tasks to complete try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } }}6. Single-Thread Scheduled Executor
Section titled “6. Single-Thread Scheduled Executor”A single-threaded scheduled executor is used to schedule tasks in a single thread.
import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;
public class SingleThreadScheduledExecutorExample { public static void main(String[] args) { ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.schedule(() -> { System.out.println("Task executed after 2 seconds delay in thread: " + Thread.currentThread().getName()); }, 2, TimeUnit.SECONDS);
scheduler.shutdown(); }}Important Considerations
Section titled “Important Considerations”Shutting Down Executors
Section titled “Shutting Down Executors”It is important to shut down the executor after tasks are completed to release resources.
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;
public class ShutdownExample { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i = 1; i <= 5; i++) { int taskId = i; executor.submit(() -> { System.out.println("Executing Task " + taskId + " in thread: " + Thread.currentThread().getName()); }); }
executor.shutdown(); // Initiates an orderly shutdown System.out.println("Executor shutdown initiated."); }}Best Practices
Section titled “Best Practices”- Always shut down executors when they are no longer needed
- Choose the appropriate executor type based on your use case:
- Use
SingleThreadExecutorfor sequential tasks - Use
FixedThreadPoolfor CPU-intensive tasks - Use
CachedThreadPoolfor short-lived tasks - Use
ScheduledThreadPoolfor periodic tasks - Use
WorkStealingPoolfor dynamic workload balancing
- Use
- Consider the number of threads carefully to avoid resource exhaustion
- Handle exceptions appropriately in submitted tasks
When to Use Which Threadpool
Section titled “When to Use Which Threadpool”