1.使用背景
在项目中,会遇到很多业务逻辑是不需要及时完成的,又不想一直卡在耗时任务上,比如在与第三方公司对接的时候,经常会遇到异步编程,这个时候就可以使用Spring提供的@Async。
2.处理方式
- 调用后,不返回任何数据
- 调用后,返回数据,通过Future来获取返回的数据
- 不返回数据处理方式
3.异步处理
3.1配置文件
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurerSupport {
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler(){
return new CusAsyncExceptionHandler();
}
@Bean("executor")
public Executor executor(){
System.out.println("executor 线程启动---");
ThreadPoolTaskExecutor scheduler = new ThreadPoolTaskExecutor();
scheduler.setCorePoolSize(5); //基本线程数量
scheduler.setQueueCapacity(500); //队列最大长度
scheduler.setMaxPoolSize(5); //最大线程数量
scheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
scheduler.setThreadNamePrefix("Myself-Executor-");
scheduler.setKeepAliveSeconds(30); //允许空闲时间
scheduler.initialize();
return scheduler;
}
}
3.2异常处理
mport jdk.nashorn.internal.runtime.logging.Logger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import java.lang.reflect.Method;
@Logger
public class CusAsyncExceptionHandler extends SimpleAsyncUncaughtExceptionHandler {
private static final Log log = LogFactory.getLog(CusAsyncExceptionHandler.class);
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... params) {
StringBuilder info = new StringBuilder();
String msg = throwable.getMessage() != null ? throwable.getMessage() : throwable.getClass().getSimpleName();
info.append("出现异常:").append(msg).append(" methodName: "+method).append("\n");
for (StackTraceElement stackTrace : throwable.getStackTrace()) {
info.append(stackTrace.toString()).append("\n");
}
log.error(info.toString());
}
}
3.3执行方法
注意:执行的方法要单独拉出一个类来,用@Componet标记,不能与Service层在一处,这里是一个坑哦
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.concurrent.Future;
@Component
public class AsyncMethod {
@Async("executor")
public void asyncMethod(){
for(int i=0;i<100;i++){
System.out.println("i: "+i+" threadName: "+Thread.currentThread());
}
int i=100/0;//抛出异常
}
@Async("executor")
public Future<Integer> asyncSquare(int x) {
System.out.println("calling asyncSquare," + Thread.currentThread().getName() + "," + new Date());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("asyncSquare Finished," + Thread.currentThread().getName() + "," + new Date());
return new AsyncResult<Integer>(x+x);
}
}
3.4Controller层
import jdk.nashorn.internal.runtime.logging.Logger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@RestController
@Logger
public class AsyncController {
private static final Log log = LogFactory.getLog(AsyncController.class);
@Autowired
private AsyncMethod asyncMethod;
@RequestMapping(value = "/async/method")
public void asyncTestMethod(){
asyncMethod.asyncMethod();
System.out.println("检测异步执行");
}
@RequestMapping(value = "/async/add")
public void asyncTestMethodAdd() throws ExecutionException, InterruptedException {
Future<Integer> result = asyncMethod.asyncSquare(9);
while (true){
if(result.isCancelled()){
log.info("async task is Cancelled");
break;
}
if(result.isDone()){
log.info("async task is Done");
log.info("result is " + result.get());
break;
}
}
System.out.println("检测异步执行");
}
3.5在postman进行调用
执行结果并且捕获异常