1、配置线程池相关参数
package com.xxx.test.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Slf4j
@Configuration
@EnableAsync(proxyTargetClass = true)
public class AsyncConfig implements AsyncConfigurer {
@Bean("asyncExecutor")
public Executor asyncExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(3);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(Integer.MAX_VALUE);
executor.setThreadNamePrefix("common-async-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
/**
* 只能捕获无返回值的异步方法,有返回值的被主线程处理
*/
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CustomAsyncExceptionHandler();
}
/***
* 处理异步方法中未捕获的异常
*/
class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
log.info("Exception message - {}", throwable.getMessage());
log.info("Method name - {}", method.getName());
log.info("Parameter values - {}", Arrays.toString(obj));
if (throwable instanceof Exception) {
Exception exception = (Exception) throwable;
log.info("exception:{}", exception.getMessage());
}
throwable.printStackTrace();
}
}
}
2、编写异步服务
package com.xxx.xxx.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import java.util.concurrent.Future;
@Slf4j
@Service
public class AsyncService {
@Async("asyncExecutor")
public void task1() throws Exception {
log.info("task1开始执行");
Thread.sleep(3000);
log.info("task1执行结束");
throw new RuntimeException("出现异常");
}
//todo 只能捕获无返回值的异步方法,有返回值的被主线程处理,还是要在主线程判断代码
@Async("asyncExecutor")
public Future<String> task2() throws Exception {
log.info("task2开始执行");
Thread.sleep(3000);
log.info("task2执行结束");
throw new RuntimeException("出现异常");
// return new AsyncResult<String>("task2 success");
}
@Async("asyncExecutor")
public Future<Integer> task3(Integer num) throws Exception {
log.info("task3开始执行,num:{}", num);
//Thread.sleep(3000);
log.info("task3执行结束,num:{}", num);
return new AsyncResult<Integer>(num);
}
@Async("asyncExecutor")
public Future<String> task4() throws Exception {
log.info("task4开始执行");
Thread.sleep(3000);
log.info("task4执行结束");
return new AsyncResult<String>("task4 success");
}
}
3、controller层服务调用
@RequestMapping(value = "/getTest", method = RequestMethod.GET)
public BasicResult getTest(Integer num) throws Exception {
BasicResult<String> basicResult = new BasicResult<>();
log.info("{} 接受到请求:num={}", Thread.currentThread().getName(), num);
//TimeUnit.HOURS.sleep(1);
asyncService.task1();
asyncService.task2();
Future<Integer> integerFuture = asyncService.task3(num);
basicResult.setSingleResult(integerFuture.get().toString());
return basicResult;
}
4、如果启用异步线程池,需要在启动类加上 @EnableAsync(proxyTargetClass = true) 注解