Java : ExecutorService - API使用例

ExecutorService (Java SE 17 & JDK 17) の使用例まとめです。
だいたいのメソッドを網羅済みです。
API仕様のおともにどうぞ。


概要

クラス構成

ExecutorServiceを使うと、タスクを非同期で実行できます。
また、タスクの実行状況は Future として追跡できます。

ExecutorServiceを生成するには、Executors ユーティリティクラスを使います。

非同期の処理をしたい場合は、Threadクラスを直接使うより ExecutorService を使うことをおすすめします。

final var executorService = Executors.newSingleThreadExecutor();
try {
    final Callable<String> task = () -> {
        try {
            System.out.println("task start");
            Thread.sleep(1000);
            return "abcd";
        } finally {
            System.out.println("task end");
        }
    };

    final var future = executorService.submit(task);

    final var ret = future.get();
    System.out.println("future get : " + ret);

} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task start
//task end
//future get : abcd
//term : true

同期(synchronized)の注意点については「synchronizedの多いコードは危険信号」もご参照いただけたら幸いです。

メソッド

boolean awaitTermination (long timeout, TimeUnit unit)

シャットダウン要求後にすべてのタスクが実行を完了していたか、タイム・アウトが発生するか、現在のスレッドで割込みが発生するか、そのいずれかが最初に発生するまでブロックします。

final var executorService = Executors.newSingleThreadExecutor();
try {
    executorService.submit(() -> {
        try {
            System.out.println("task start");
            Thread.sleep(1000);
            System.out.println("Run!");

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        } finally {
            System.out.println("task end");
        }
    });
} finally {
    // shutdownでは割込み(InterruptedException)は発生しません。
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(2, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task start
//Run!
//task end
//term : true
final var executorService = Executors.newSingleThreadExecutor();
try {
    executorService.submit(() -> {
        try {
            System.out.println("task start");
            Thread.sleep(2000);
            System.out.println("Run!");

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

} finally {
    executorService.shutdown();
}

// 1秒だけ待ちます。実行中のタスクは2秒スリープしているので、結果としてfalseを返します。
final var ret = executorService.awaitTermination(1, TimeUnit.SECONDS);
System.out.println("term 1 : " + ret);

// さらに2秒待ちます。タスクは完了するのでtrueを返します。
final var ret2 = executorService.awaitTermination(2, TimeUnit.SECONDS);
System.out.println("term 2 : " + ret2);

// 結果
// ↓
//task start
//term 1 : false
//Run!
//task end
//term 2 : true

<T> List<Future<T>> invokeAll (Collection<? extends Callable<T>> tasks)

指定されたタスクを実行し、すべて完了すると、ステータスと結果を含むFutureのリストを返します。

final var executorService = Executors.newWorkStealingPool(3);
final var tasks = List.<Callable<String>>of(
        () -> {
            try {
                System.out.println("task 1 : start");
                Thread.sleep(1000);
                return "aaa";
            } finally {
                System.out.println("task 1 : end");
            }
        },
        () -> {
            try {
                System.out.println("task 2 : start");
                Thread.sleep(1000);
                return "bbb";
            } finally {
                System.out.println("task 2 : end");
            }
        },
        () -> {
            try {
                System.out.println("task 3 : start");
                Thread.sleep(1000);
                return "ccc";
            } finally {
                System.out.println("task 3 : end");
            }
        }
);

try {
    System.out.println("-- invoke start --");

    final var futures = executorService.invokeAll(tasks);

    System.out.println("-- invoke end --");

    for (final var future : futures) {
        System.out.println("get : " + future.get());
    }

} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//-- invoke start --
//task 1 : start
//task 2 : start
//task 3 : start
//task 1 : end
//task 2 : end
//task 3 : end
//-- invoke end --
//get : aaa
//get : bbb
//get : ccc
//term : true

<T> List<Future<T>> invokeAll (Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)

指定されたタスクを実行し、すべてが完了するか時間切れになるか、そのいずれかが最初に発生した時点で、ステータスと結果を含むFutureのリストを返します。

final var executorService = Executors.newFixedThreadPool(3);
final var tasks = List.<Callable<String>>of(
        () -> {
            try {
                System.out.println("task 1 : start");
                Thread.sleep(1000);
                return "aaa";
            } catch (InterruptedException e) {
                System.out.println("task 1 : Interrupted!");
                return null;
            } finally {
                System.out.println("task 1 : end");
            }
        }, () -> {
            try {
                System.out.println("task 2 : start");
                Thread.sleep(3000);
                return "bbb";
            } catch (InterruptedException e) {
                System.out.println("task 2 : Interrupted!");
                return null;
            } finally {
                System.out.println("task 2 : end");
            }
        }, () -> {
            try {
                System.out.println("task 3 : start");
                Thread.sleep(5000);
                return "ccc";
            } catch (InterruptedException e) {
                System.out.println("task 3 : Interrupted!");
                return null;
            } finally {
                System.out.println("task 3 : end");
            }
        });

try {
    System.out.println("-- invoke start --");

    // 4秒で完了するのは、1番目 "aaa" と 2番目の "bbb" タスク。
    final var futures = executorService.invokeAll(tasks, 4000, TimeUnit.MILLISECONDS);

    System.out.println("-- invoke end --");

    System.out.println("futures size : " + futures.size());

    for (final var future : futures) {
        if (future.isCancelled()) {
            System.out.println("Cancelled!");
            continue;
        }

        System.out.println("future get : " + future.get());
    }

} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//-- invoke start --
//task 1 : start
//task 2 : start
//task 3 : start
//task 1 : end
//task 2 : end
//-- invoke end --
//task 3 : Interrupted!
//task 3 : end
//futures size : 3
//future get : aaa
//future get : bbb
//Cancelled!
//term : true

<T> T invokeAny (Collection<? extends Callable<T>> tasks)

指定されたタスクを実行し、例外をスローせずに正常に完了したタスクが存在する場合は、その結果を返します。

final var executorService = Executors.newWorkStealingPool(3);
final var tasks = List.<Callable<String>>of(
        () -> {
            try {
                System.out.println("task 1 : start");
                Thread.sleep(100);
                throw new IllegalStateException();
            } catch (InterruptedException e) {
                System.out.println("task 1 : Interrupted!");
                return null;
            } finally {
                System.out.println("task 1 : end");
            }
        }, () -> {
            try {
                System.out.println("task 2 : start");
                Thread.sleep(200);
                return "bbb";
            } catch (InterruptedException e) {
                System.out.println("task 2 : Interrupted!");
                return null;
            } finally {
                System.out.println("task 2 : end");
            }
        }, () -> {
            try {
                System.out.println("task 3 : start");
                Thread.sleep(300);
                return "ccc";
            } catch (InterruptedException e) {
                System.out.println("task 3 : Interrupted!");
                return null;
            } finally {
                System.out.println("task 3 : end");
            }
        });

try {
    System.out.println("-- invoke start --");

    final var ret = executorService.invokeAny(tasks);

    System.out.println("-- invoke end --");

    System.out.println("task ret : " + ret);

} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//-- invoke start --
//task 1 : start
//task 2 : start
//task 3 : start
//task 1 : end
//task 2 : end
//-- invoke end --
//task 3 : Interrupted!
//task 3 : end
//task ret : bbb
//term : true

<T> T invokeAny (Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)

指定されたタスクを実行し、タイム・アウトが経過する前に例外をスローせずに正常に完了したタスクが存在する場合は、その結果を返します。

final var executorService = Executors.newFixedThreadPool(3);
final var tasks = List.<Callable<String>>of(
        () -> {
            try {
                System.out.println("task 1 : start");
                Thread.sleep(500);
                throw new IllegalStateException();
            } catch (InterruptedException e) {
                System.out.println("task 1 : Interrupted!");
                return null;
            } finally {
                System.out.println("task 1 : end");
            }
        }, () -> {
            try {
                System.out.println("task 2 : start");
                Thread.sleep(1000);
                return "bbb";
            } catch (InterruptedException e) {
                System.out.println("task 2 : Interrupted!");
                return null;
            } finally {
                System.out.println("task 2 : end");
            }
        }, () -> {
            try {
                System.out.println("task 3 : start");
                Thread.sleep(3000);
                return "ccc";
            } catch (InterruptedException e) {
                System.out.println("task 3 : Interrupted!");
                return null;
            } finally {
                System.out.println("task 3 : end");
            }
        });
try {
    System.out.println("-- invoke start --");

    final var ret = executorService.invokeAny(tasks, 2000, TimeUnit.MILLISECONDS);

    System.out.println("-- invoke end --");

    System.out.println("task ret : " + ret);

} catch (TimeoutException e) {
    System.out.println("Timeout!");
} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//-- invoke start --
//task 1 : start
//task 2 : start
//task 3 : start
//task 1 : end
//task 2 : end
//-- invoke end --
//task 3 : Interrupted!
//task 3 : end
//task ret : bbb
//term : true
final var executorService = Executors.newFixedThreadPool(2);
final var tasks = List.<Callable<String>>of(
        () -> {
            try {
                System.out.println("task 1 : start");
                Thread.sleep(2000);
                return "aaa";
            } catch (InterruptedException e) {
                System.out.println("task 1 : Interrupted!");
                return null;
            } finally {
                System.out.println("task 1 : end");
            }
        }, () -> {
            try {
                System.out.println("task 2 : start");
                Thread.sleep(3000);
                return "bbb";
            } catch (InterruptedException e) {
                System.out.println("task 2 : Interrupted!");
                return null;
            } finally {
                System.out.println("task 2 : end");
            }
        });

try {
    System.out.println("-- invoke start --");

    final var ret = executorService.invokeAny(tasks, 1000, TimeUnit.MILLISECONDS);

    System.out.println("-- invoke end --");

    System.out.println("task ret : " + ret);

} catch (TimeoutException e) {
    System.out.println("Timeout!");
} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//-- invoke start --
//task 1 : start
//task 2 : start
//Timeout!
//task 1 : Interrupted!
//task 2 : Interrupted!
//task 1 : end
//task 2 : end
//term : true

boolean isShutdown ()

このexecutorがシャットダウンしていた場合、trueを返します。

final var executorService = Executors.newSingleThreadExecutor();
try {
    executorService.submit(() -> {
        try {
            System.out.println("task start");
            Thread.sleep(1000);

        } catch (InterruptedException e) {
            System.out.println("Interrupted!");
        } finally {
            System.out.println("task end");
        }
    });
} finally {
    Thread.sleep(100);

    System.out.println("isShutdown : " + executorService.isShutdown());
    System.out.println("isTerminated : " + executorService.isTerminated());

    executorService.shutdown();
    System.out.println("--- shutdown ---");

    System.out.println("isShutdown : " + executorService.isShutdown());
    System.out.println("isTerminated : " + executorService.isTerminated());
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

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

System.out.println("isTerminated : " + executorService.isTerminated());

// 結果
// ↓
//task start
//isShutdown : false
//isTerminated : false
//--- shutdown ---
//isShutdown : true
//isTerminated : false
//task end
//term : true
//--- awaitTermination ---
//isTerminated : true

boolean isTerminated ()

シャットダウンに続いてすべてのタスクが完了していた場合、trueを返します。

このメソッドの使用例は、isShutdown() にまとめて記載しました。
そちらのAPI使用例をご参照ください。

void shutdown ()

順序正しくシャットダウンを開始します。以前に送信されたタスクが実行されますが、新規タスクは受け入れられません。

final var executorService = Executors.newSingleThreadExecutor();
try {
    final Runnable task1 = () -> {
        try {
            System.out.println("task1 start");
            Thread.sleep(1000);

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

    executorService.submit(task1);
    Thread.sleep(100);

} finally {
    // 実行中のタスクはそのまま実行を継続します。
    executorService.shutdown();
    System.out.println("--- shutdown ---");
}

try {
    // shutdown後は新規のタスクを受け付けません。(RejectedExecutionException発生)
    executorService.submit(() -> System.out.println("task2"));

} catch (RejectedExecutionException e) {
    System.out.println("submit : Reject!");
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task1 start
//--- shutdown ---
//submit : Reject!
//task1 end
//term : true

List<Runnable> shutdownNow ()

実行中のアクティブなタスクすべての停止を試み、待機中のタスクの処理を停止し、実行を待機していたタスクのリストを返します。

final var executorService = Executors.newSingleThreadExecutor();
try {
    executorService.submit(() -> {
        try {
            System.out.println("task1 : start");
            Thread.sleep(2000);
            System.out.println("task1 : run");

        } catch (InterruptedException e) {
            System.out.println("task1 : Interrupted!");
        } finally {
            System.out.println("task1 : end");
        }
    });
    executorService.submit(() -> {
        System.out.println("task2 : run");
    });
    executorService.submit(() -> {
        System.out.println("task3 : run");
    });

    Thread.sleep(1000);

} finally {
    System.out.println("--- shutdownNow ---");
    final var notExecutedTasks = executorService.shutdownNow();

    Thread.sleep(1000);

    System.out.println("--- not executed tasks ---");
    System.out.println("size : " + notExecutedTasks.size());

    for (final var task : notExecutedTasks) {
        task.run();
    }
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task1 : start
//--- shutdownNow ---
//task1 : Interrupted!
//task1 : end
//--- not executed tasks ---
//size : 2
//task2 : run
//task3 : run
//term : true
final var executorService = Executors.newSingleThreadExecutor();
try {
    executorService.submit(() -> {
        try {
            System.out.println("task1 : start");
            Thread.sleep(2000);
            System.out.println("task1 : run");

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

    Thread.sleep(1000);

} finally {
    System.out.println("--- shutdownNow ---");
    executorService.shutdownNow();

    Thread.sleep(1000);
}

try {
    // shutdownNow後は新規のタスクを受け付けません。(RejectedExecutionException発生)
    executorService.submit(() -> {
        System.out.println("task2 : run");
    });

} catch (RejectedExecutionException e) {
    System.out.println("submit : Reject!");
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task1 : start
//--- shutdownNow ---
//task1 : Interrupted!
//task1 : end
//submit : Reject!
//term : true

Future<?> submit (Runnable task)

実行用のRunnableタスクを送信し、そのタスクを表すFutureを返します。

final var executorService = Executors.newSingleThreadExecutor();
try {
    final Runnable task = () -> {
        try {
            System.out.println("task start");
            Thread.sleep(1000);
            System.out.println("task run");

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

    final var future = executorService.submit(task);

    Thread.sleep(100);

    // タスクが終了するまで待機。
    System.out.println("-- future get --");
    future.get();

    System.out.println("future isDone : " + future.isDone());

} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task start
//-- future get --
//task run
//task end
//future isDone : true
//term : true

<T> Future<T> submit (Runnable task, T result)

実行用のRunnableタスクを送信し、そのタスクを表すFutureを返します。

final var executorService = Executors.newSingleThreadExecutor();
try {
    final Runnable task = () -> {
        try {
            System.out.println("task start");
            Thread.sleep(1000);
            System.out.println("task run");

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

    final var future = executorService.submit(task, "abcd");

    Thread.sleep(100);

    // タスクが終了するまで待機。
    System.out.println("-- future get --");
    final var ret = future.get();

    System.out.println("future ret : " + ret);
    System.out.println("future isDone : " + future.isDone());

} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task start
//-- future get --
//task run
//task end
//future ret : abcd
//future isDone : true
//term : true

<T> Future<T> submit (Callable<T> task)

値を返す実行用タスクを送信して、保留状態のタスク結果を表すFutureを返します。

final var executorService = Executors.newSingleThreadExecutor();
try {
    final Callable<String> task = () -> {
        try {
            System.out.println("task start");
            Thread.sleep(1000);
            return "abcd";
        } finally {
            System.out.println("task end");
        }
    };

    final var future = executorService.submit(task);

    Thread.sleep(100);

    // タスクが終了するまで待機。
    System.out.println("-- future get --");
    final var ret = future.get();

    System.out.println("future ret : " + ret);
    System.out.println("future isDone : " + future.isDone());

} finally {
    executorService.shutdown();
}

final var ret = executorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// 結果
// ↓
//task start
//-- future get --
//task end
//future ret : abcd
//future isDone : true
//term : true

Executorで宣言されたメソッド

execute

Java API 使用例 : Executor」をご参照ください。


関連記事

ページの先頭へ