首页 > 解决方案 > 将 Java `ExecutorService` 与 Spring `TaskExecutor` 混合使用

问题描述

我有一段我以前在没有 Spring 的情况下使用的 Java 代码,如下所示:

// `Callable` instead of `Runnable` because we need to throw exceptions
public MyTask extends Callable<Void> {
  @Override
  public Void call() throws Exception { ... }
}

public class MyTasksRunner {

  private final ExecutorService executorService;

  ...

  public void run() throws Exception {
    List<MyTask> tasks = ...;
    var futures = executorService.invokeAll(tasks);
    for (var future : futures) {
      // Rethrow any exceptions happened in the threads.
      future.get();
    }
  }
}

现在我将这段代码合并到一个启用了异步的更大的 Spring Boot 应用程序中。它配置一个TaskExecutor,它没有与 相同的接口ExecutorService。ATaskExecutor只能运行Runnables,不能运行Callables。

我可能同时拥有一个TaskExecutor用于异步 Spring 的 bean,以及另一个ExecutorService用于MyTasksRunner代码的 bean。但我想知道如果我想合并这些选项我有什么选择:

我也想过只制作MyTask一个 Spring 组件并用 注释它@Async,但我真的不喜欢它使MyTask*代码与 Spring 绑定。

标签: javaspringspring-boot

解决方案


是的,您可以将您的Callable任务转换Runnable为我认为您不期望任何返回值。但是有一个条件 - 你不能抛出 Checked Exception 但是你可以继续抛出 Runtime Exception。

另外,是的,您可以如下定义Executorbean 来注入ExecutorService

@Bean
public Executor taskExecutor() {

    ExecutorService executor = Executors.newFixedThreadPool(2);

    return executor;
}

如果您没有定义 Executor bean,Spring 会创建SimpleAsyncTaskExecutor并使用它。


推荐阅读