【Java】Springで@Asyncを使わずに非同期化する方法
実行環境
@Asyncを使えないケース
- 呼び出し元によって同期/非同期を選択したい
- 対象メソッドのシグネチャを変えたくない/変えられない
- 戻り値がある場合はFuture型に変更する必要がある
@Asyncを使わない非同期化方法
- Configurationクラスに@EnableAsyncを付与する
- Executorを定義する
- Executorをインジェクションする
- CompletableFutureのrunAsync/supplyAsyncで非同期化する
1. Configurationクラスに@EnableAsyncを付与する
@EnableAsync @Configuration public class AsyncConfiguration {...}
SpringBootの場合はApplicationクラスでもOK
@EnableAsync @SpringBootApplication public class AsyncApplication {...}
2. Executorを定義する
Configuration(Application)クラスにExecutorのBeanを定義をする
@Bean("taskExecutor") public Executor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setThreadNamePrefix("TaskThread-"); executor.initialize(); return executor; }
3. ExecutorをDIする
4. CompletableFutureのsupplyAsync/runAsyncで非同期化する
@RestController public class AsyncController { private final Service service; private final Executor executor; public AsyncController(Service service, @Qualifier("taskExecutor") Executor executor) { this.service= service; this.executor = executor; } @GetMapping("/") public String index() { CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> service.execute(), executor); try { String result = cf.get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } return ""; } }
ポイントは以下
- 定義したExecutorを@QualifierでDIする
- DIしたExecutorをsupplyAsync/runAsyncの引数に指定する