Java : Executors with Examples

Executors (Java SE 19 & JDK 19) API Examples.
You will find code examples on most Executors methods.


Summary

Factory and utility methods for Executor, ExecutorService, ScheduledExecutorService, ThreadFactory, and Callable classes defined in this package.

Class diagram

try (final var executorService = Executors.newSingleThreadExecutor()) {
    final Runnable task = () -> {
        System.out.println("  task start");
        System.out.println("  thread id = " + Thread.currentThread().threadId());
    };

    System.out.println("-- submit start --");
    System.out.println("thread id = " + Thread.currentThread().threadId());
    executorService.submit(task);
    System.out.println("-- submit end --");
}

System.out.println("-- terminated --");

// Result
// ↓
//-- submit start --
//thread id = 1
//-- submit end --
//  task start
//  thread id = 33
//-- terminated --

Methods

static Callable<Object> callable (Runnable task)

Returns a Callable object that, when called, runs the given task and returns null.

final var callable = Executors.callable(() -> System.out.println("abcd"));

final var ret = callable.call(); // abcd
System.out.println(ret); // null

static <T> Callable<T> callable (Runnable task, T result)

Returns a Callable object that, when called, runs the given task and returns the given result.

final var callable = Executors.callable(() -> System.out.println("abcd"), "XYZ");

final var ret = callable.call(); // abcd
System.out.println(ret); // XYZ

static Callable<Object> callable (PrivilegedAction<?> action)

Returns a Callable object that, when called, runs the given privileged action and returns its result.

final var privilegedAction = new PrivilegedAction<>() {
    @Override
    public Object run() {
        System.out.println("abcd");
        return "XYZ";
    }
};

final var callable = Executors.callable(privilegedAction);

final var ret = callable.call(); // abcd
System.out.println(ret); // XYZ

static Callable<Object> callable (PrivilegedExceptionAction<?> action)

Returns a Callable object that, when called, runs the given privileged exception action and returns its result.

final var privilegedExceptionAction = new PrivilegedExceptionAction<>() {
    @Override
    public Object run() {
        System.out.println("abcd");
        return "XYZ";
    }
};

final var callable = Executors.callable(privilegedExceptionAction);

final var ret = callable.call(); // abcd
System.out.println(ret); // XYZ

static ThreadFactory defaultThreadFactory ()

Returns a default thread factory used to create new threads.

final var threadFactory = Executors.defaultThreadFactory();

final var thread = threadFactory.newThread(() -> {
    System.out.println("Run!");
});

System.out.println("thread id : " + thread.threadId());
System.out.println("thread name : " + thread.getName());
System.out.println("thread priority : " + thread.getPriority());

System.out.println("-- start --");
thread.start();

thread.join();
System.out.println("-- join --");

// Result
// ↓
//thread id : 33
//thread name : pool-1-thread-1
//thread priority : 5
//-- start --
//Run!
//-- join --

static ExecutorService newCachedThreadPool ()

Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available.

class Task implements Runnable {
    private final String name;

    Task(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        try {
            System.out.printf("%s : start (thread id = %d)%n",
                    name, Thread.currentThread().threadId());

            TimeUnit.SECONDS.sleep(1);

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        } finally {
            System.out.println(name + " : end");
        }
    }
}

try (var executorService = Executors.newCachedThreadPool()) {
    executorService.submit(new Task("task1"));
    executorService.submit(new Task("task2"));
    executorService.submit(new Task("task3"));

    TimeUnit.SECONDS.sleep(2);

    executorService.submit(new Task("task4"));
    executorService.submit(new Task("task5"));
}

// Result
// ↓
//task1 : start (thread id = 33)
//task2 : start (thread id = 34)
//task3 : start (thread id = 35)
//task1 : end
//task2 : end
//task3 : end
//task4 : start (thread id = 33)
//task5 : start (thread id = 35)
//task4 : end
//task5 : end

static ExecutorService newCachedThreadPool (ThreadFactory threadFactory)

Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available, and uses the provided ThreadFactory to create new threads when needed.

class Task implements Runnable {
    private final String name;

    Task(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        try {
            System.out.printf("%s : start (thread name = %s)%n",
                    name, Thread.currentThread().getName());

            TimeUnit.SECONDS.sleep(1);

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        } finally {
            System.out.println(name + " : end");
        }
    }
}

try (final var executorService = Executors.newCachedThreadPool(r -> {
    final var thread = new Thread(r);
    thread.setName("TID:" + thread.threadId());
    return thread;
})) {
    executorService.submit(new Task("task1"));
    executorService.submit(new Task("task2"));
    executorService.submit(new Task("task3"));

    TimeUnit.SECONDS.sleep(2);

    executorService.submit(new Task("task4"));
    executorService.submit(new Task("task5"));
}

// Result
// ↓
//task1 : start (thread name = TID:33)
//task2 : start (thread name = TID:34)
//task3 : start (thread name = TID:35)
//task1 : end
//task2 : end
//task3 : end
//task4 : start (thread name = TID:34)
//task5 : start (thread name = TID:35)
//task4 : end
//task5 : end

static ExecutorService newFixedThreadPool (int nThreads)

Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue.

class Task implements Runnable {
    private final String name;

    Task(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        try {
            System.out.printf("%s : start (thread id = %d)%n",
                    name, Thread.currentThread().threadId());

            TimeUnit.SECONDS.sleep(1);

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        } finally {
            System.out.println(name + " : end");
        }
    }
}

try (final var executorService = Executors.newFixedThreadPool(3)) {
    executorService.submit(new Task("task1"));
    executorService.submit(new Task("task2"));
    executorService.submit(new Task("task3"));
    executorService.submit(new Task("task4"));
    executorService.submit(new Task("task5"));
}

// Result
// ↓
//task1 : start (thread id = 33)
//task2 : start (thread id = 34)
//task3 : start (thread id = 35)
//task1 : end
//task2 : end
//task3 : end
//task4 : start (thread id = 33)
//task5 : start (thread id = 35)
//task4 : end
//task5 : end

static ExecutorService newFixedThreadPool (int nThreads, ThreadFactory threadFactory)

Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue, using the provided ThreadFactory to create new threads when needed.

class Task implements Runnable {
    private final String name;

    Task(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        try {
            System.out.printf("%s : start (thread name = %s)%n",
                    name, Thread.currentThread().getName());

            TimeUnit.SECONDS.sleep(1);

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        } finally {
            System.out.println(name + " : end");
        }
    }
}

try (final var executorService = Executors.newFixedThreadPool(3, r -> {
    final var thread = new Thread(r);
    thread.setName("TID:" + thread.threadId());
    return thread;
})) {
    executorService.submit(new Task("task1"));
    executorService.submit(new Task("task2"));
    executorService.submit(new Task("task3"));
    executorService.submit(new Task("task4"));
    executorService.submit(new Task("task5"));
}

// Result
// ↓
//task1 : start (thread name = TID:33)
//task2 : start (thread name = TID:34)
//task3 : start (thread name = TID:35)
//task1 : end
//task2 : end
//task3 : end
//task4 : start (thread name = TID:34)
//task5 : start (thread name = TID:35)
//task4 : end
//task5 : end

static ScheduledExecutorService newScheduledThreadPool (int corePoolSize)

Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically.

class Task implements Runnable {
    private final String name;
    private final long currentTime;

    Task(String name, long currentTime) {
        this.name = name;
        this.currentTime = currentTime;
    }

    @Override
    public void run() {
        try {
            System.out.printf("%s : start (thread id = %d) : %f sec.%n",
                    name, Thread.currentThread().threadId(), getElapsedTime());

            TimeUnit.SECONDS.sleep(1);

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        } finally {
            System.out.println(name + " : end : " + getElapsedTime() + " sec.");
        }
    }

    private double getElapsedTime() {
        return (System.nanoTime() - currentTime) / 1000000000.0;
    }
}

try (final var executorService = Executors.newScheduledThreadPool(3)) {
    final var currentTime = System.nanoTime();

    executorService.schedule(new Task("task1", currentTime), 3, TimeUnit.SECONDS);
    executorService.schedule(new Task("task2", currentTime), 5, TimeUnit.SECONDS);
    executorService.schedule(new Task("task3", currentTime), 7, TimeUnit.SECONDS);

    executorService.submit(new Task("task4", currentTime));
    executorService.submit(new Task("task5", currentTime));
}

// Result
// ↓
//task4 : start (thread id = 35) : 0.001707 sec.
//task5 : start (thread id = 34) : 0.001720 sec.
//task4 : end : 1.0058648 sec.
//task5 : end : 1.0060478 sec.
//task1 : start (thread id = 33) : 3.001571 sec.
//task1 : end : 4.0130198 sec.
//task2 : start (thread id = 34) : 5.010234 sec.
//task2 : end : 6.0181524 sec.
//task3 : start (thread id = 35) : 7.001654 sec.
//task3 : end : 8.0131763 sec.

static ScheduledExecutorService newScheduledThreadPool (int corePoolSize, ThreadFactory threadFactory)

Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically.

class Task implements Runnable {
    private final String name;
    private final long currentTime;

    Task(String name, long currentTime) {
        this.name = name;
        this.currentTime = currentTime;
    }

    @Override
    public void run() {
        try {
            System.out.printf("%s : start (thread name = %s) : %f sec.%n",
                    name, Thread.currentThread().getName(), getElapsedTime());

            TimeUnit.SECONDS.sleep(1);

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        } finally {
            System.out.println(name + " : end : " + getElapsedTime() + " sec.");
        }
    }

    private double getElapsedTime() {
        return (System.nanoTime() - currentTime) / 1000000000.0;
    }
}

try (final var executorService = Executors.newScheduledThreadPool(3, r -> {
    final var thread = new Thread(r);
    thread.setName("TID:" + thread.threadId());
    return thread;
})) {
    final var currentTime = System.nanoTime();

    executorService.schedule(new Task("task1", currentTime), 3, TimeUnit.SECONDS);
    executorService.schedule(new Task("task2", currentTime), 5, TimeUnit.SECONDS);
    executorService.schedule(new Task("task3", currentTime), 7, TimeUnit.SECONDS);

    executorService.submit(new Task("task4", currentTime));
    executorService.submit(new Task("task5", currentTime));
}

// Result
// ↓
//task4 : start (thread name = TID:34) : 0.005763 sec.
//task5 : start (thread name = TID:35) : 0.005858 sec.
//task4 : end : 1.0167864 sec.
//task5 : end : 1.0167499 sec.
//task1 : start (thread name = TID:33) : 3.009088 sec.
//task1 : end : 4.0211626 sec.
//task2 : start (thread name = TID:35) : 5.016738 sec.
//task2 : end : 6.0314814 sec.
//task3 : start (thread name = TID:34) : 7.012653 sec.
//task3 : end : 8.0254665 sec.

static ExecutorService newSingleThreadExecutor ()

Creates an Executor that uses a single worker thread operating off an unbounded queue.

class Task implements Runnable {
    private final String name;

    Task(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        try {
            System.out.printf("%s : start (thread id = %d)%n",
                    name, Thread.currentThread().threadId());

            TimeUnit.SECONDS.sleep(1);

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        } finally {
            System.out.println(name + " : end");
        }
    }
}

try (final var executorService = Executors.newSingleThreadExecutor()) {
    executorService.submit(new Task("task1"));
    executorService.submit(new Task("task2"));
    executorService.submit(new Task("task3"));
}

// Result
// ↓
//task1 : start (thread id = 33)
//task1 : end
//task2 : start (thread id = 33)
//task2 : end
//task3 : start (thread id = 33)
//task3 : end

static ExecutorService newSingleThreadExecutor (ThreadFactory threadFactory)

Creates an Executor that uses a single worker thread operating off an unbounded queue, and uses the provided ThreadFactory to create a new thread when needed.

class Task implements Runnable {
    private final String name;

    Task(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        try {
            System.out.printf("%s : start (thread name = %s)%n",
                    name, Thread.currentThread().getName());

            TimeUnit.SECONDS.sleep(1);

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        } finally {
            System.out.println(name + " : end");
        }
    }
}

try (final var executorService = Executors.newSingleThreadExecutor(r -> {
    final var thread = new Thread(r);
    thread.setName("TID:" + thread.threadId());
    return thread;
})) {
    executorService.submit(new Task("task1"));
    executorService.submit(new Task("task2"));
    executorService.submit(new Task("task3"));
}

// Result
// ↓
//task1 : start (thread name = TID:33)
//task1 : end
//task2 : start (thread name = TID:33)
//task2 : end
//task3 : start (thread name = TID:33)
//task3 : end

static ScheduledExecutorService newSingleThreadScheduledExecutor ()

Creates a single-threaded executor that can schedule commands to run after a given delay, or to execute periodically.

class Task implements Runnable {
    private final String name;
    private final long currentTime;

    Task(String name, long currentTime) {
        this.name = name;
        this.currentTime = currentTime;
    }

    @Override
    public void run() {
        try {
            System.out.printf("%s : start (thread id = %d) : %f sec.%n",
                    name, Thread.currentThread().threadId(), getElapsedTime());

            TimeUnit.SECONDS.sleep(1);

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        } finally {
            System.out.println(name + " : end : " + getElapsedTime() + " sec.");
        }
    }

    private double getElapsedTime() {
        return (System.nanoTime() - currentTime) / 1000000000.0;
    }
}

try (final var executorService = Executors.newSingleThreadScheduledExecutor()) {
    final var currentTime = System.nanoTime();

    executorService.schedule(new Task("task1", currentTime), 3, TimeUnit.SECONDS);
    executorService.schedule(new Task("task2", currentTime), 5, TimeUnit.SECONDS);

    executorService.submit(new Task("task3", currentTime));
}

// Result
// ↓
//task3 : start (thread id = 33) : 0.001784 sec.
//task3 : end : 1.0113467 sec.
//task1 : start (thread id = 33) : 3.009510 sec.
//task1 : end : 4.0228934 sec.
//task2 : start (thread id = 33) : 5.010346 sec.
//task2 : end : 6.0217522 sec.

static ScheduledExecutorService newSingleThreadScheduledExecutor (ThreadFactory threadFactory)

Creates a single-threaded executor that can schedule commands to run after a given delay, or to execute periodically.

class Task implements Runnable {
    private final String name;
    private final long currentTime;

    Task(String name, long currentTime) {
        this.name = name;
        this.currentTime = currentTime;
    }

    @Override
    public void run() {
        try {
            System.out.printf("%s : start (thread name = %s) : %f sec.%n",
                    name, Thread.currentThread().getName(), getElapsedTime());

            TimeUnit.SECONDS.sleep(1);

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        } finally {
            System.out.println(name + " : end : " + getElapsedTime() + " sec.");
        }
    }

    private double getElapsedTime() {
        return (System.nanoTime() - currentTime) / 1000000000.0;
    }
}

try (final var executorService = Executors.newSingleThreadScheduledExecutor(r -> {
    final var thread = new Thread(r);
    thread.setName("TID:" + thread.threadId());
    return thread;
})) {
    final var currentTime = System.nanoTime();

    executorService.schedule(new Task("task1", currentTime), 3, TimeUnit.SECONDS);
    executorService.schedule(new Task("task2", currentTime), 5, TimeUnit.SECONDS);

    executorService.submit(new Task("task3", currentTime));
}

// Result
// ↓
//task3 : start (thread name = TID:33) : 0.005336 sec.
//task3 : end : 1.0096395 sec.
//task1 : start (thread name = TID:33) : 3.001487 sec.
//task1 : end : 4.0157305 sec.
//task2 : start (thread name = TID:33) : 5.012736 sec.
//task2 : end : 6.0237463 sec.

static ExecutorService newThreadPerTaskExecutor (ThreadFactory threadFactory)

Preview. Creates an Executor that starts a new Thread for each task.

Preview.

static ExecutorService newVirtualThreadPerTaskExecutor ()

Preview. Creates an Executor that starts a new virtual Thread for each task.

Preview.

static ExecutorService newWorkStealingPool ()

Creates a work-stealing thread pool using the number of available processors as its target parallelism level.

class Task implements Runnable {
    private final String name;

    Task(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        try {
            System.out.printf("%s : start (thread id = %d)%n",
                    name, Thread.currentThread().threadId());

            TimeUnit.SECONDS.sleep(1);

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        } finally {
            System.out.println(name + " : end");
        }
    }
}

try (final var executorService = Executors.newWorkStealingPool()) {
    executorService.submit(new Task("task1"));
    executorService.submit(new Task("task2"));
    executorService.submit(new Task("task3"));
    executorService.submit(new Task("task4"));
    executorService.submit(new Task("task5"));
}

// Result
// ↓
//task1 : start (thread id = 33)
//task2 : start (thread id = 34)
//task3 : start (thread id = 35)
//task4 : start (thread id = 36)
//task5 : start (thread id = 37)
//task1 : end
//task2 : end
//task3 : end
//task4 : end
//task5 : end

static ExecutorService newWorkStealingPool (int parallelism)

Creates a thread pool that maintains enough threads to support the given parallelism level, and may use multiple queues to reduce contention.

class Task implements Runnable {
    private final String name;

    Task(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        try {
            System.out.printf("%s : start (thread id = %d)%n",
                    name, Thread.currentThread().threadId());

            TimeUnit.SECONDS.sleep(1);

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        } finally {
            System.out.println(name + " : end");
        }
    }
}

try (final var executorService = Executors.newWorkStealingPool(3)) {
    executorService.submit(new Task("task1"));
    executorService.submit(new Task("task2"));
    executorService.submit(new Task("task3"));
    executorService.submit(new Task("task4"));
    executorService.submit(new Task("task5"));
}

// Result
// ↓
//task1 : start (thread id = 33)
//task2 : start (thread id = 34)
//task3 : start (thread id = 35)
//task1 : end
//task2 : end
//task3 : end
//task4 : start (thread id = 33)
//task5 : start (thread id = 34)
//task4 : end
//task5 : end

static <T> Callable<T> privilegedCallable (Callable<T> callable)

Deprecated, for removal: This API element is subject to removal in a future version. This method is only useful in conjunction with the Security Manager, which is deprecated and subject to removal in a future release.

Deprecated.

static <T> Callable<T> privilegedCallableUsingCurrentClassLoader (Callable<T> callable)

Deprecated, for removal: This API element is subject to removal in a future version. This method is only useful in conjunction with the Security Manager, which is deprecated and subject to removal in a future release.

Deprecated.

static ThreadFactory privilegedThreadFactory ()

Deprecated, for removal: This API element is subject to removal in a future version. This method is only useful in conjunction with the Security Manager, which is deprecated and subject to removal in a future release.

Deprecated.

static ExecutorService unconfigurableExecutorService (ExecutorService executor)

Returns an object that delegates all defined ExecutorService methods to the given executor, but not any other methods that might otherwise be accessible using casts.

// An example without unconfigurableExecutorService.
try (final var executorService = Executors.newFixedThreadPool(3)) {
    // Can be downcast.
    final var threadPoolExecutor = (ThreadPoolExecutor) executorService;

    threadPoolExecutor.setCorePoolSize(1);
    System.out.println(threadPoolExecutor.getCorePoolSize()); // 1
}
// An example with unconfigurableExecutorService.
try (final var executorService = Executors.unconfigurableExecutorService(
        Executors.newFixedThreadPool(3))) {

    // Can be not downcast.
    final var threadPoolExecutor = (ThreadPoolExecutor) executorService;

} catch (ClassCastException e) {
    System.out.println("ClassCastException!");
}

// Result
// ↓
//ClassCastException!

static ScheduledExecutorService unconfigurableScheduledExecutorService (ScheduledExecutorService executor)

Returns an object that delegates all defined ScheduledExecutorService methods to the given executor, but not any other methods that might otherwise be accessible using casts.

// An example without unconfigurableScheduledExecutorService.
try (final var scheduledExecutorService = Executors.newScheduledThreadPool(3)) {
    // Can be downcast.
    final var threadPoolExecutor = (ScheduledThreadPoolExecutor) scheduledExecutorService;

    threadPoolExecutor.setCorePoolSize(1);
    System.out.println(threadPoolExecutor.getCorePoolSize()); // 1
}
// An example with unconfigurableScheduledExecutorService.
try (final var scheduledExecutorService = Executors.unconfigurableScheduledExecutorService(
        Executors.newScheduledThreadPool(3))) {

    // Can be not downcast.
    final var threadPoolExecutor = (ScheduledThreadPoolExecutor) scheduledExecutorService;

} catch (ClassCastException e) {
    System.out.println("ClassCastException!");
}

// Result
// ↓
//ClassCastException!

Related posts

To top of page