如何在Spring Boot @Async中使用ForkJoinPool?

时间:2019-01-25 12:12:21

标签: java spring spring-boot java.util.concurrent forkjoinpool

我想在Spring Boot项目中使用带有ThreadPoolTask​​Executor之类的@Async注释的ForkJoinPool

例如:-

 @Bean("threadPoolTaskExecutor")
    public TaskExecutor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(20);
        executor.setMaxPoolSize(1000);
        executor.setThreadNamePrefix("Async-");
        return executor;
    }

我在代码中使用https://dzone.com/articles/spring-boot-creating-asynchronous-methods-using-as此链接,但我想这样使用ForkJoinPool。

4 个答案:

答案 0 :(得分:3)

我认为您不能将@Async注释与ForkJoinPool类结合使用。 ForkJoinPool致力于将一个任务拆分为子任务,以并行方式执行该任务并将其合并为结果。后台有using ForkJoinPool个并行流。要使用ForkJoinPool执行任务,您需要实现RecursiveTaskRecursiveAction接口。我没有见过如何一起使用这些东西的方法。

答案 1 :(得分:1)

最好将Asknch与ForkJoinPool一起使用。这种方法并非完全是ForkJoinPool设计的目的-解决分而治之的任务并使用工作窃取算法,而是执行事件样式或IO阻止任务,这是一个有效的用例。

因此,通过基本用法,您可以执行以下操作:

CompletableFuture.runAsync(() -> doSomething(), ForkJoinPool.commonPool());

您还可以在Asynch模式下创建自定义ForkJoinPool。异步模式下的ForkJoinPool中的工作人员以FIFO(先进先出)顺序处理任务。默认情况下,ForkJoinPools以LIFO(后进先出)顺序处理此类任务。另外,异步模式设置仅涉及从未加入的分叉任务。可以用于已提交但从未加入的事件式任务(执行的任务具有副作用,而不是返回将由派生任务处理然后加入的结果)。

您可以像这样在异步模式下创建具有给定并行性的自定义ForkJoinPool(第一个参数是池大小,最后一个-bool asyncMode):

ForkJoinPool pool = new ForkJoinPool(
             6, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true);

所以你追求的是:

    @Bean("threadPoolTaskExecutor")
    public Executor getAsyncExecutor() {
    ForkJoinPool pool = new ForkJoinPool(
             6, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true);
        return pool;
    }

答案 2 :(得分:1)

我不知道您为什么要这样做,但是您仍然可以对ForkJoinPool使用@Async,因为ForkJoinPool正在实现Executor的类

但是,如果我们查看ForkJoinPool-documentation,我看不到任何设置线程池大小的方法,那么使用它是您的风险。

配置

@Bean("threadPoolTaskExecutor")
public Executor getAsyncExecutor() {
    ForkJoinPool pool = new ForkJoinPool();
    return pool;
}

服务

@Async("threadPoolTaskExecutor")
public void testRun()  {
    System.out.println(Thread.currentThread().getName());
}

输出

ForkJoinPool-1-worker-1

如果您非常想使用ForkJoinPool,请使用CompletableFuture.async方法而不是spring boot @Async docs

  

所有没有显式Executor参数的异步方法都是使用ForkJoinPool.commonPool()执行的(除非它不支持并行度至少为2,在这种情况下,将创建一个新的线程来运行每个任务)

答案 3 :(得分:0)

要启用Spring的异步方法执行功能,您可以在配置类中使用@EnableAsync批注。

@Configuration
@EnableAsync
public class ThreadConfig {
    @Bean
    public TaskExecutor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(4);
        executor.setMaxPoolSize(4);
        executor.setThreadNamePrefix("prate");
        executor.initialize();
        return executor;
    }
}

在某些情况下,您不希望同一线程池运行该应用程序的所有任务。您可能需要具有不同配置的单独线程池来支持我们的功能。 因此,您可以配置特定的ThreadPoolExecutor,例如-

@Configuration
@EnableAsync
public class ThreadConfig {
    @Bean(name = "specificTaskExecutor")
    public TaskExecutor specificTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.initialize();
        return executor;
    }
}

现在,该函数应设置限定符值,以确定特定执行程序或TaskExecutor的目标执行程序。

@Async("specificTaskExecutor")
public void runFromAnotherThreadPool() {
    System.out.println("test here");
}