盘点Spring中的线程池,及如何在Spring异步任务使用自定义的线程池。

Spring中的内置线程池

SimpleAsyncTaskExecutor

实现了TaskExecutor接口,为每个任务创建一个线程,并异步执行它,可以通过setConcurrencyLimit设置最大的创建线程数,不适用大量执行时间短的任务。

SyncTaskExecutor

同步的,谁调用谁执行,一般用于测试。

1
2
3
4
public void execute(Runnable task) {
Assert.notNull(task, "Runnable must not be null");
task.run();
}

ConcurrentTaskExecutor

Executor的适配类,暴露出Spring的TaskExecutor类。不推荐直接使用。

ThreadPoolTaskExecutor

最常用,对java.util.concurrent.ThreadPoolExecutor的包装,可以运行时指定线程池的大小。

Spring定时调度

定时调度的配置和使用

使用注解配置:

1
2
@EnableAsync
@EnableScheduling

<task:*> XML 命名空间中的功能。

1
2
3
4
5
@Scheduled(cron = "0/5 * * * * ?")
@Async
public void taskOne() {
log.info("线程id:[{}]的定时任务执行...", Thread.currentThread().getName());
}

使用自定义线程池

默认情况下,Spring 将搜索关联的线程池定义:上下文中唯一的org.springframework.core.task.TaskExecutor bean,或者名为“taskExecutor”的java.util.concurrent.Executor bean。 如果两者都不可解析,则将使用org.springframework.core.task.SimpleAsyncTaskExecutor来处理异步方法调用。 此外,具有void返回类型的带注释的方法不能将任何异常传输回调用者。 默认情况下,仅记录此类未捕获的异常。
实现org.springframework.scheduling.annotation.AsyncConfigurer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Configuration
@EnableAsync
@Slf4j
public class AppConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(42);
executor.setQueueCapacity(11);
executor.setThreadNamePrefix("MyExecutor-");
executor.initialize();
return executor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (ex, m, p) -> log.info("执行任务异常:{},{}", m, ex);
}
}

继承AsyncConfigurerSupport
同实现接口一样。

在spring容器中创建taskExecutor的bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration
public class TaskPoolConfig {

@Bean(name = "taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(42);
executor.setQueueCapacity(11);
executor.setThreadNamePrefix("自定义线程池-");
executor.initialize();
return executor;
}
}