在一个 @Async 方法中使用的线程池与其他异步方法执行共享

Threadpool used in one @Async method getting shared with other async method executions

我有一个线程池初始化为@Bean,用于专门执行特定的@Async 方法

class MyConfig {
    @Bean(name="myPool")
    public static TaskExecutor getExecutor(){
        ThreadPooltaskExecutor exec = new ThreadPoolTaskExecutor();
        exec.setCorePoolSize(1);
        exec.setMaxPoolSize(1);
        exec.setThreadNamePrefix("my-thread");
        exec.initialize();
        return exec;
    }
}

上面的线程池作为 bean 在异步方法调用中使用,如下所示:

public class MyHandler {
    ...
    @Async("myPool")
    public void handle(){
        ...
        logger.INFO("do my thing");
        ...
    }
    ...
}

还有其他 类 也在使用默认 Spring @Async 池,例如:

public class OtherScheduledTask {
    ...
    @Async
    public void doThat() {
        logger.INFO("doing that thing");
    }
    ...
}

在 运行 应用程序上,我可以在日志中看到以下内容:

[pool-1-thread-1] [] c.c.a.m.p.e.c.OtherScheduledTask - do my thing
[myPool] [] c.c.a.m.p.e.c.MyHandler - doing that thing
....

我看到上面的日志片段随机打印,默认线程池和自定义线程池间歇性地执行异步方法

我确实有从非异步方法调用@Async 方法的场景

但是,我严格只在 MyHandler 中使用一个 @Async 方法 handle() 来使用我的自定义线程池,而没有在其他地方使用

为什么 spring 混合使用线程池(自定义和默认)来执行 @async 方法?

在@Async方法注解中传递bean名有什么用?

我如何使用一种特定的异步方法拥有专用的线程池,以便在它不执行时让线程池空闲并且不被其他仅应默认执行的异步方法使用spring线程池

关于我的环境的详细信息: Spring 启动版本 1.4.2 RELEASE JDK1.8.0

关于 Spring 和代理的一个关键问题是许多带注释的功能使用代理来提供功能。也就是说 @Transactional@Cacheable@Async 都依赖于 Spring 检测这些注释并将这些 bean 包装在代理 bean 中。

在这种情况下,代理方法只能在 on the class 中调用时使用,而不能在 within 中调用class。有关该主题,请参阅 this

引用评论:

@Dovmo I am invoking one async method with custom pool from non-async method in same class. Other async methods are getting invoked from their respective classes and there is no calls across these methods from other classes

尝试重构并从上下文中的另一个 class 调用那些 @Async 方法,或者通过 self-autowiring 将 class 调用到自身并以这种方式调用异步方法。

[除了关于 Spring 如何与代理方法一起工作的内容 - 以及从以下位置调用 @Async 方法的正确上下文:]

引用官方Spring文档:

By default, Spring will be searching for an associated thread pool definition: either a unique TaskExecutor bean in the context, or an Executor bean named "taskExecutor" otherwise. If neither of the two is resolvable, a SimpleAsyncTaskExecutor will be used to process async method invocations.

假设您的代码片段中缺少一些注释,该代码只是添加了另一个可能的执行器供 Spring 查找和使用。您需要显式覆盖 Spring 的默认 SimpleAsyncTaskExecutor 实现:

方法一:覆盖默认实现(来自官方文档)

 @Configuration
 @EnableAsync
 public class AppConfig implements AsyncConfigurer {

     @Override
     public Executor getAsyncExecutor() {
         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         executor.setCorePoolSize(7);
         executor.setMaxPoolSize(42);
         executor.setQueueCapacity(11);
         executor.setThreadNamePrefix("MyExecutor-");
         executor.initialize();
         return executor;
     }

     @Override
     public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
         return MyAsyncUncaughtExceptionHandler();
     }
 }

方法 2:提供自定义和默认实现:

@Configuration
 @EnableAsync
 public class AppConfig implements AsyncConfigurer {

     // Provide an Executor implementation in lieu of the default Spring implementation
    @Override
    @Bean
    @Primary
    public Executor getAsyncExecutor() {        
        SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor("pool1-");
        return executor;
    }

     @Bean(name="myCustomExecutor")
     public Executor getAsyncExecutor() {
         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         executor.setCorePoolSize(7);
         executor.setMaxPoolSize(42);
         executor.setQueueCapacity(11);
         executor.setThreadNamePrefix("MyExecutor-");
         executor.initialize();
         return executor;
     }

     @Override
     public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
         return MyAsyncUncaughtExceptionHandler();
     }
 }

P.S:如果你的getExecutor()被注释为@Bean

it is no longer necessary to manually call the executor.initialize() method as this will be invoked automatically when the bean is initialized.