Java : ExecutorService - API使用例
ExecutorService (Java SE 19 & JDK 19) の使用例まとめです。
だいたいのメソッドを網羅済みです。
API仕様のおともにどうぞ。
概要
ExecutorService を使うと、タスクを非同期に実行できます。
また、タスクの実行状況は Future として追跡できます。
ExecutorService を生成するには、Executors ユーティリティクラスを使います。
非同期の処理をしたい場合は、Threadクラスを直接使うより ExecutorService を使うことをおすすめします。
ノート
- Java 19 から、ExecutorService は AutoCloseable を実装するようになりました。 これにより try-with-resources文 でリソースを自動で解放できます。
try (final var executorService = Executors.newSingleThreadExecutor()) {
final Callable<String> task = () -> {
try {
System.out.println("task start");
TimeUnit.SECONDS.sleep(1);
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);
}
// 結果
// ↓
//task start
//task end
//future get : abcd
同期(synchronized)の注意点については「synchronizedの多いコードは危険信号」もご参照いただけたら幸いです。
メソッド
boolean awaitTermination (long timeout, TimeUnit unit)
final var executorService = Executors.newSingleThreadExecutor();
try {
executorService.submit(() -> {
try {
System.out.println("task start");
TimeUnit.SECONDS.sleep(1);
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");
TimeUnit.SECONDS.sleep(2);
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
default void close ()
可能であれば try-with-resources文 を使うことをおすすめします。
System.out.println("-- start --");
try (final var executorService = Executors.newSingleThreadExecutor()) {
final Callable<Void> task = () -> {
try {
System.out.println(" task start");
System.out.println(" sleep...");
TimeUnit.SECONDS.sleep(1);
} finally {
System.out.println(" task end");
}
return null;
};
executorService.submit(task);
System.out.println("submit end");
}
System.out.println("-- end --");
// 結果
// ↓
//-- start --
//submit end
// task start
// sleep...
// task end
//-- end --
try-with-resources文を使わない例です。
System.out.println("-- start --");
final var executorService = Executors.newSingleThreadExecutor();
try {
final Callable<Void> task = () -> {
try {
System.out.println(" task start");
System.out.println(" sleep...");
TimeUnit.SECONDS.sleep(1);
} finally {
System.out.println(" task end");
}
return null;
};
executorService.submit(task);
System.out.println("submit end");
} finally {
executorService.close();
}
System.out.println("-- end --");
// 結果
// ↓
//-- start --
//submit end
// task start
// sleep...
// task end
//-- end --
<T> List<Future<T>> invokeAll (Collection<? extends Callable<T>> tasks)
final var tasks = List.<Callable<String>>of(
() -> {
try {
System.out.println("task 1 : start");
TimeUnit.SECONDS.sleep(1);
return "aaa";
} finally {
System.out.println("task 1 : end");
}
},
() -> {
try {
System.out.println("task 2 : start");
TimeUnit.SECONDS.sleep(1);
return "bbb";
} finally {
System.out.println("task 2 : end");
}
},
() -> {
try {
System.out.println("task 3 : start");
TimeUnit.SECONDS.sleep(1);
return "ccc";
} finally {
System.out.println("task 3 : end");
}
}
);
try (final var executorService = Executors.newFixedThreadPool(3)) {
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());
}
}
// 結果
// ↓
//-- 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
<T> List<Future<T>> invokeAll (Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
final var tasks = List.<Callable<String>>of(
() -> {
try {
System.out.println("task 1 : start");
TimeUnit.SECONDS.sleep(1);
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");
TimeUnit.SECONDS.sleep(3);
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");
TimeUnit.SECONDS.sleep(5);
return "ccc";
} catch (InterruptedException e) {
System.out.println("task 3 : Interrupted!");
return null;
} finally {
System.out.println("task 3 : end");
}
});
try (final var executorService = Executors.newFixedThreadPool(3)) {
System.out.println("-- invoke start --");
// 4秒で完了するのは、1番目 "aaa" と 2番目の "bbb" タスク。
final var futures = executorService.invokeAll(tasks, 4, TimeUnit.SECONDS);
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());
}
}
// 結果
// ↓
//-- 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!
<T> T invokeAny (Collection<? extends Callable<T>> tasks)
final var tasks = List.<Callable<String>>of(
() -> {
System.out.println("task 1 : start");
TimeUnit.SECONDS.sleep(1);
System.out.println("task 1 : throw IllegalStateException!");
throw new IllegalStateException();
}, () -> {
try {
System.out.println("task 2 : start");
TimeUnit.SECONDS.sleep(2);
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");
TimeUnit.SECONDS.sleep(3);
return "ccc";
} catch (InterruptedException e) {
System.out.println("task 3 : Interrupted!");
return null;
} finally {
System.out.println("task 3 : end");
}
});
try (final var executorService = Executors.newFixedThreadPool(3)) {
System.out.println("-- invoke start --");
final var ret = executorService.invokeAny(tasks);
System.out.println("-- invoke end --");
System.out.println("task ret : " + ret);
}
// 結果
// ↓
//-- invoke start --
//task 1 : start
//task 2 : start
//task 3 : start
//task 1 : throw IllegalStateException!
//task 2 : end
//-- invoke end --
//task 3 : Interrupted!
//task 3 : end
//task ret : bbb
<T> T invokeAny (Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
final var tasks = List.<Callable<String>>of(
() -> {
System.out.println("task 1 : start");
TimeUnit.SECONDS.sleep(1);
System.out.println("task 1 : throw IllegalStateException!");
throw new IllegalStateException();
}, () -> {
try {
System.out.println("task 2 : start");
TimeUnit.SECONDS.sleep(2);
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");
TimeUnit.SECONDS.sleep(5);
return "ccc";
} catch (InterruptedException e) {
System.out.println("task 3 : Interrupted!");
return null;
} finally {
System.out.println("task 3 : end");
}
});
try (final var executorService = Executors.newFixedThreadPool(3)) {
System.out.println("-- invoke start --");
final var ret = executorService.invokeAny(tasks, 3, TimeUnit.SECONDS);
System.out.println("-- invoke end --");
System.out.println("task ret : " + ret);
} catch (TimeoutException e) {
System.out.println("Timeout!");
}
// 結果
// ↓
//-- invoke start --
//task 1 : start
//task 2 : start
//task 3 : start
//task 1 : throw IllegalStateException!
//task 2 : end
//-- invoke end --
//task 3 : Interrupted!
//task 3 : end
//task ret : bbb
final var tasks = List.<Callable<String>>of(
() -> {
try {
System.out.println("task 1 : start");
TimeUnit.SECONDS.sleep(2);
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");
TimeUnit.SECONDS.sleep(3);
return "bbb";
} catch (InterruptedException e) {
System.out.println("task 2 : Interrupted!");
return null;
} finally {
System.out.println("task 2 : end");
}
});
try (final var executorService = Executors.newFixedThreadPool(2)) {
System.out.println("-- invoke start --");
final var ret = executorService.invokeAny(tasks, 1, TimeUnit.SECONDS);
System.out.println("-- invoke end --");
System.out.println("task ret : " + ret);
} catch (TimeoutException e) {
System.out.println("Timeout!");
}
// 結果
// ↓
//-- invoke start --
//task 1 : start
//task 2 : start
//task 1 : Interrupted!
//task 2 : Interrupted!
//task 1 : end
//task 2 : end
//Timeout!
boolean isShutdown ()
try (final var executorService = Executors.newWorkStealingPool()) {
final var future = executorService.submit(() -> {
System.out.println("task start");
return "abcd";
});
final var ret = future.get();
System.out.println("future get : " + ret);
System.out.println("isShutdown : " + executorService.isShutdown());
System.out.println("isTerminated : " + executorService.isTerminated());
}
// 結果
// ↓
//task start
//future get : abcd
//isShutdown : false
//isTerminated : false
final var executorService = Executors.newSingleThreadExecutor();
try {
executorService.submit(() -> {
try {
System.out.println("task start");
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
System.out.println("Interrupted!");
} finally {
System.out.println("task end");
}
});
TimeUnit.SECONDS.sleep(1);
} finally {
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 ()
このメソッドの使用例は、isShutdown() にまとめて記載しました。
そちらのAPI使用例をご参照ください。
void shutdown ()
final var executorService = Executors.newSingleThreadExecutor();
try {
final Runnable task1 = () -> {
try {
System.out.println("task1 start");
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
System.out.println("Interrupted!");
} finally {
System.out.println("task1 end");
}
};
executorService.submit(task1);
TimeUnit.SECONDS.sleep(1);
} 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");
TimeUnit.SECONDS.sleep(2);
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");
});
TimeUnit.SECONDS.sleep(1);
} finally {
System.out.println("--- shutdownNow ---");
final var notExecutedTasks = executorService.shutdownNow();
TimeUnit.SECONDS.sleep(1);
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");
TimeUnit.SECONDS.sleep(2);
System.out.println("task1 : run");
} catch (InterruptedException e) {
System.out.println("task1 : Interrupted!");
} finally {
System.out.println("task1 : end");
}
});
TimeUnit.SECONDS.sleep(1);
} finally {
System.out.println("--- shutdownNow ---");
executorService.shutdownNow();
}
TimeUnit.SECONDS.sleep(1);
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)
try (final var executorService = Executors.newSingleThreadExecutor()) {
final Runnable task = () -> {
try {
System.out.println("task start");
TimeUnit.SECONDS.sleep(2);
System.out.println("task run");
} catch (InterruptedException e) {
System.out.println("Interrupted!");
} finally {
System.out.println("task end");
}
};
final var future = executorService.submit(task);
TimeUnit.SECONDS.sleep(1);
// タスクが終了するまで待機。
System.out.println("-- future get --");
future.get();
System.out.println("future isDone : " + future.isDone());
}
// 結果
// ↓
//task start
//-- future get --
//task run
//task end
//future isDone : true
<T> Future<T> submit (Runnable task, T result)
try (final var executorService = Executors.newSingleThreadExecutor()) {
final Runnable task = () -> {
try {
System.out.println("task start");
TimeUnit.SECONDS.sleep(2);
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");
TimeUnit.SECONDS.sleep(1);
// タスクが終了するまで待機。
System.out.println("-- future get --");
final var ret = future.get();
System.out.println("future ret : " + ret);
System.out.println("future isDone : " + future.isDone());
}
// 結果
// ↓
//task start
//-- future get --
//task run
//task end
//future ret : abcd
//future isDone : true
<T> Future<T> submit (Callable<T> task)
try (final var executorService = Executors.newSingleThreadExecutor()) {
final Callable<String> task = () -> {
try {
System.out.println("task start");
TimeUnit.SECONDS.sleep(2);
return "abcd";
} finally {
System.out.println("task end");
}
};
final var future = executorService.submit(task);
TimeUnit.SECONDS.sleep(1);
// タスクが終了するまで待機。
System.out.println("-- future get --");
final var ret = future.get();
System.out.println("future ret : " + ret);
System.out.println("future isDone : " + future.isDone());
}
// 結果
// ↓
//task start
//-- future get --
//task end
//future ret : abcd
//future isDone : true
Executorで宣言されたメソッド
execute
「Java API 使用例 : Executor」をご参照ください。
関連記事
- API 使用例
- BlockingQueue (ブロッキング・キュー)
- Callable
- CancellationException
- ConcurrentHashMap.KeySetView (並列処理用セット)
- ConcurrentLinkedDeque (並列処理用・両端キュー)
- ConcurrentLinkedQueue (並列処理用キュー)
- ConcurrentMap (並列処理用マップ)
- ConcurrentModificationException (並列処理例外)
- ConcurrentSkipListSet (並列処理用セット)
- Condition (同期)
- CopyOnWriteArrayList (並列処理用リスト)
- CopyOnWriteArraySet (並列処理用セット)
- CountDownLatch (同期)
- CyclicBarrier (同期)
- Exchanger (同期)
- Executor
- Executors
- Future
- Future.State
- FutureTask
- InterruptedException (割込み例外)
- Lock (同期)
- Object (オブジェクト)
- Runnable
- Semaphore (セマフォ)
- Thread (スレッド)
- ThreadGroup
- ThreadLocal
- TimeUnit