Java ExecutorService Class

ExecutorService is a core interface in Java concurrent programming, it belongs to thejava.util.concurrentpackage.

ExecutorService provides a more advanced way of thread management, allowing developers to efficiently execute asynchronous tasks without manually creating and managing threads.

The main functions of ExecutorService include:

  • Thread pool management: Automatically manage the lifecycle of threads, reducing the overhead of thread creation and destruction.
  • Task scheduling: Supports submittingRunnableorCallabletasks, and returnsFutureobjects to track task execution status.
  • Resource optimization: Reuse threads through the thread pool to improve system performance.

Core Methods of ExecutorService

ExecutorService provides multiple methods to submit, manage, and control task execution. Here are a few key methods:

submit()

Used to submit a task (RunnableorCallable) and returnFutureobject to check whether the task is completed or to get the return value.

Example

ExecutorService executor = Executors.newFixedThreadPool(2);
Future<?> future = executor.submit(() -> {
    System.out.println("Task is running");
});

execute()

Only used to submitRunnabletasks, without returning any results.

Example

executor.execute(() -> {
    System.out.println("Task executed");
});

shutdown()

Gracefully shut down the thread pool, no longer accept new tasks, but wait for already submitted tasks to complete.

Example

executor.shutdown();

shutdownNow()

Immediately shut down the thread pool, attempt to interrupt all running tasks, and return the list of tasks that were not executed.

Example

List<Runnable> notExecutedTasks = executor.shutdownNow();

awaitTermination()

Wait for the thread pool to shut down until all tasks complete or a timeout occurs.

Example

executor.awaitTermination(10, TimeUnit.SECONDS);

How to Create ExecutorService

Java providesExecutorsutility class to create different types of thread pools:

newFixedThreadPool(int nThreads)

Create a fixed-size thread pool, suitable for tasks with stable load.

Example

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);

newCachedThreadPool()

Create a cached thread pool, suitable for short-lived asynchronous tasks.

Example

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

newSingleThreadExecutor()

Create a single-threaded thread pool, suitable for tasks executed sequentially.

Example

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

newScheduledThreadPool(int corePoolSize)

Create a thread pool that supports scheduled or periodic tasks.

Example

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2);

Usage Examples

Submitting Runnable Tasks

Example

ExecutorService executor = Executors.newFixedThreadPool(2);

executor.submit(() -> {
    System.out.println("Task 1 running");
});

executor.submit(() -> {
    System.out.println("Task 2 running");
});

executor.shutdown();

Submitting Callable Tasks and Getting Results

Example

ExecutorService executor = Executors.newFixedThreadPool(2);

Future<String> future = executor.submit(() -> {
    Thread.sleep(1000);
    return "Task completed";
});

try {
    String result = future.get(); // Blocks until the task completes
    System.out.println(result);
} catch (Exception e) {
    e.printStackTrace();
}

executor.shutdown();

Best Practices

  1. Reasonably Set Thread Pool Size:

    • CPU-intensive tasks:线程数 = CPU 核心数 + 1
    • IO-intensive tasks:线程数 = CPU 核心数 * 2
  2. Avoid Memory Leaks:

    • Make sure to callshutdown()orshutdownNow()to shut down the thread pool.
  3. Handle Exceptions:

    • Usetry-catchto catch exceptions in tasks, preventing threads from terminating unexpectedly.
  4. UseFutureto manage tasks:

    • ThroughFuture.get()get task results or check task status.
Other Extensions