我有一个初始化为@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 Boot版本1.4.2 RELEASE JDK 1.8.0
答案 0 :(得分:1)
关于Spring和代理的一件事是,许多带注释的功能都使用代理来提供功能。即@Transactional
,@Cacheable
和@Async
都依赖于Spring检测这些注释并将这些bean包装在代理bean中。
在这种情况下,仅当在类中的上调用该代理方法时,才可以使用该方法。有关该主题,请参见this。
引用评论:
@Dovmo我正在从非异步调用一种带有自定义池的异步方法 同一类中的方法。其他异步方法正在从中调用 它们各自的类,并且这些方法之间没有调用 来自其他班级
尝试重构并从上下文中的另一个类中调用这些@Async
方法,或者通过self-autowiring将类插入自身并以这种方式调用异步方法。
答案 1 :(得分:1)
[除了关于Spring如何与代理方法一起使用的说法之外-还有从以下位置调用@Async方法的正确上下文:]
默认情况下,Spring将搜索关联的线程池定义:上下文中的唯一TaskExecutor bean,否则为名为“ taskExecutor”的Executor bean。如果两者都不能解决,则将使用SimpleAsyncTaskExecutor处理异步方法调用。
假设您的代码片段中缺少一些注释,则该代码仅添加了另一个可能的执行程序,供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();
}
}
@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
注释:
不再需要手动调用executor.initialize() 方法,因为当Bean是 初始化。