@Async指定的执行程序是否可用于CompletableFuture.supplyAsync(supplier)?

时间:2018-12-07 02:23:30

标签: java spring spring-boot

我有遗嘱执行人,

@Bean("someExecutor")
public Executor someExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(2);
    executor.setMaxPoolSize(2);
    executor.setQueueCapacity(500);
    executor.setThreadNamePrefix("AsyncMethod-");
    executor.initialize();
    return executor;
}

和异步方法。

@Async("someExecutor")
public Future<List<String>> someMethod(){
    return CompletableFuture.supplyAsync(() -> {
        //long time job
        return listGeneratedByLongTimeJob;
    });
}

Spring将对someMethod使用someExecutor吗?又如何?

我知道supplyAsync(supplier)的重载方法是supplyAsync(supplier,executor),下面的代码怎么样?

@Autowired("someExecutor")
private Executor executor;

@Async()
public Future<List<String>> someMethod(){
    return CompletableFuture.supplyAsync(() -> {
        //long time job
        return listGeneratedByLongTimeJob;
    }, executor);
}

谢谢。

1 个答案:

答案 0 :(得分:1)

好吧,花点时间才能弄清楚这一点,在进入两种情况之前,我们需要讨论{ "name": "todo-list", "version": "0.1.0", "description": "Add and remove items from a list", "author": "Crystal", "private": true, "dependencies": { "express": "^4.16.4", "react": "^16.6.3", "react-dom": "^16.6.3", "react-scripts": "2.1.1", "react-signup-login-component": "^1.2.0" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, "eslintConfig": { "extends": "react-app" }, "browserslist": [ ">0.2%", "not dead", "not ie <= 11", "not op_mini all" ], "devDependencies": { "@babel/core": "^7.2.0", "@babel/preset-env": "^7.2.0", "babel-loader": "^8.0.4", "cypress": "^3.1.3" } }

来自java.util.concurrent.CompletableFuture docs

  

所有没有显式Executor参数的异步方法都是使用ForkJoinPool.commonPool()执行的(除非它不支持并行度至少为两个,在这种情况下,将创建一个新的线程)运行每个任务)。为了简化监视,调试和跟踪,所有生成的异步任务都是标记接口CompletableFuture.AsynchronousCompletionTask的实例。

因此,当您每次调用ForkJoinPool时,供应商将由CompletableFuture.supplyAsync(Supplier s)线程执行,现在让我们开始案例1

案例1:

为清楚起见,我添加了一些ForkJoinPool语句以打印线程名称

sysout

输出:

@Async("someExecutor")
public Future<String> asyncService() {
    System.out.println();

    System.out.println(Thread.currentThread().getName()+" - "+Thread.currentThread().getThreadGroup());

    System.out.println();
    return CompletableFuture.supplyAsync(()->{

    System.out.println(Thread.currentThread().getName()+" - "+Thread.currentThread().getThreadGroup());
        return "hello";
    });

}

在这种情况下,AsyncMethod-1 - java.lang.ThreadGroup[name=main,maxpri=10] ForkJoinPool.commonPool-worker-1 - java.lang.ThreadGroup[name=main,maxpri=10] asyncService()线程执行,并且 AsyncMethod-1中的provider由supplyAsync()

执行

情况2:

ForkJoinPool

输出:

@Autowired
private Executor someExecutor;


@Async
public Future<String> asyncService() {
    System.out.println();

    System.out.println(Thread.currentThread().getName()+" - "+Thread.currentThread().getThreadGroup());

    System.out.println();
    return CompletableFuture.supplyAsync(()->{

    System.out.println(Thread.currentThread().getName()+" - "+Thread.currentThread().getThreadGroup());
        return "hello";
    },someExecutor);

}

在第二种情况下,AsyncMethod-1 - java.lang.ThreadGroup[name=main,maxpri=10] AsyncMethod-2 - java.lang.ThreadGroup[name=main,maxpri=10] 中的方法asyncService()和供应商都使用来自supplyAsync()的线程

默认情况下,Spring使用SimpleAsyncTaskExecutor实际运行这些someExecutor pool方法,但是我们在配置中使用async docs覆盖了someExecutor

  

默认情况下,Spring将搜索关联的线程池定义:上下文中的唯一TaskExecutor bean,否则为名为“ taskExecutor”的Executor bean。如果二者都不可解决,则将使用SimpleAsyncTaskExecutor处理异步方法调用。

注意::如果您在配置类中没有@EnableAsync,则会得到不同的结果,我将在gitHub中上传此代码并在此处添加链接