- 加了@Async注解的方法和调用其的方法不能再同一个类中,否则会导致异步不起作用。
- 启用多线程需要添加
@EnableAsync
注解,添加在有@Configuration
注解的配置类上,或者SpringBoot的Application启动类上皆可。 - 通过配置类对线程池进行配置:
@Configuration
@EnableAsync
public class SpringAysncExecutorConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
// 最小线程数(核心线程数)
taskExecutor.setCorePoolSize(300);
// 最大线程数
taskExecutor.setMaxPoolSize(400);
// 等待队列(队列最大长度)
taskExecutor.setQueueCapacity(1000);
// 线程池维护线程所允许的空闲时间 ,单位s
taskExecutor.setKeepAliveSeconds(300);
// 线程池对拒绝任务(无线程可用)的处理策略
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return taskExecutor;
}
/**
* 异步异常处理
*
* @return
*/
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SpringAsyncExceptionHandler();
}
class SpringAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
// 处理异常的逻辑...
}
}
}
线程池的处理流程:
- 线程数量达到CorePoolSize时,新的任务会进队列等待;
- 如果等待队列已满,则线程池会新建线程;
- 如果队列已满,池中线程数也已达到MaxPoolSize,则开始使用配置的拒绝策略处理新的任务。
拒绝策略:
有四种拒绝策略:
// 默认策略,丢弃任务,并且抛出RejectedExecutionException异常
ThreadPoolExecutor.AbortPolicy();
// 如果任务被拒绝了,则由调用线程(提交任务的线程)直接执行此任务;
ThreadPoolExecutor.CallerRunsPolicy();
// 丢弃任务,但是不抛出异常。如果线程队列已满,则后续提交的任务都会被丢弃,且是静默丢弃。
ThreadPoolExecutor.DiscardPolicy();
// 丢弃队列最前面的任务,然后让新任务进入等待队列等待。同样是静默丢弃
ThreadPoolExecutor.DiscardOldestPolicy();
异常处理
Spring多线程的异常处理非常简单。
如之前的配置类中所示,通过实现AsyncUncaughtExceptionHandler
接口,在handleUncaughtException
方法中写异常处理逻辑。
随后在配置类中覆盖getAsyncUncaughtExceptionHandler
方法,返回我们自己定义的异常处理类即可。
需要注意的是handleUncaughtException
方法只能处理线程中未Catch住的异常,如果线程内部Catch住了异常,则该方法不会再生效。
网友评论