1. pom文件里依赖这个包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.应用启动类添加@EnableAsync注解
@SpringBootApplication
@EnableAsync
public class SpringBootStudyApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootStudyApplication.class);
}
}
3.配置异步任务线程池
由于默认的异步任务会开启始终会一个新的线程,不利于资源的重复利用,所以,要编写一个异步任务的线程池
//AsyncPoolConfig.java
@Configuration
public class AsyncPoolConfig implements AsyncConfigurer {
private final Logger logger = LoggerFactory.getLogger(MyAsyncTask.class);
@Bean
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);// 设置核心线程池线程的数量,默认是1
executor.setMaxPoolSize(20); // 线程池最大的线程数量,当核心线程都被用光,且缓冲队列是满的之后才申请
executor.setQueueCapacity(20); // 缓冲队列中任务的个数
executor.setKeepAliveSeconds(60); // 超出核心线程数的其他线程在空闲时的最大的存活时间
executor.setThreadNamePrefix("frank_"); //线程池中的线程名称前缀
executor.setWaitForTasksToCompleteOnShutdown(true);//程序关闭后,是否等待异步任务完成, 等待的时间需要配置, 默认false,
executor.setAwaitTerminationSeconds(60);// 等待的时间,默认0
//拒绝策略 线程池中的最大线程线程数用光,且缓冲队列也满了,可以选择的策略
// DiscardPolicy: 丢弃需要添加的新的任务
// AbortPolicy: 直接抛出异常
// DiscardOldestPolicy: 丢弃阻塞队列的队头任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
return executor;
}
//异步任务异常处理类,只会处理没有返回值的异步任务的异常
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler{
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
logger.info("AsyncException:{}, Method:{}, Params:{}", throwable, method, objects);
throwable.printStackTrace();
//TODO 发送邮件或者短信
}
}
}
4.编写异步任务
@Component
public class MyAsyncTask {
private final Logger logger = LoggerFactory.getLogger(MyAsyncTask.class);
@Async("getAsyncExecutor")
public void asyncProcess() throws InterruptedException {
logger.info("async process task, current thread name -> {}", Thread.currentThread().getName());
Thread.sleep(10000);
//int a = 1/0;
}
@Async("getAsyncExecutor")
public Future<Integer> asyncProcessHasReturn() throws InterruptedException {
logger.info("async process task(has return), current thread name -> {}", Thread.currentThread().getName());
Thread.sleep(10000);
//int a = 1/0;
return new AsyncResult<>(100);
}
}
5.使用
@Autowired
private MyAsyncTask myAsyncTask;
logger.info("current thread name:", Thread.currentThread().getName());
myAsyncTask.asyncProcess();
Future<Integer> result = myAsyncTask.asyncProcessHasReturn();
logger.info("reuslt:{}", result.get(1, TimeUnit.SECONDS));//1s后定时任务没执行完就抛异常