vlambda博客
学习文章列表

初识spring-boot异步编程

开始

首先 spring的官网给出了详细的教程,但是对于比较爱国的大家(以及我)可能看的模模糊糊 官网:spring-async异步编程。优秀的异步编程能使我们系统的响应速度加快用户体验更好比如某宝网的查看商品详情会出现销量数库存数量评价数量…

— 开始之前你得已经熟悉了spring-boot开发的流程。

第一步:新建一个配置类

@EnableAsync // 启用 @Async
@Configuration
public class ExecutorConfig {
@Bean
public ThreadPoolTaskExecutor asyncExecutor(){
ThreadPoolTaskExecutor tpx = new ThreadPoolTaskExecutor();
tpx.setThreadNamePrefix("pandora-task-");
tpx.setCorePoolSize(10);
tpx.setMaxPoolSize(100);
tpx.setKeepAliveSeconds(60);
return tpx;
}
}

第二步:在你需要 异步请求的接口中 添加@Asyn注解

public interface TestService {

@Async
void testAsyncNoReturns();

@Async
Future<Integer> testAsyncReturnInt();

/**
* 需要有返回值的 默认要返回Future
* @return
*/

@Async("asyncExecutor")
Future<Map<String,String>> testAsync();

}

第三步:实现接口逻辑处理。

@Service
public class TestServiceImpl implements TestService{

private static final long SlEEP_TIME = 1L;
private static final int INIT_SIZE = 5;

@Override
public void testAsyncNoReturns() {
long startTime = System.currentTimeMillis();
this.sleep();
System.out.println("testAsyncNoReturns()->线程名:" + Thread.currentThread().getName());
System.out.println("testAsyncNoReturns() ->消耗时间:" + (System.currentTimeMillis() - startTime));
}

@Override
public Future<Integer> testAsyncReturnInt() {
long startTime = System.currentTimeMillis();
this.sleep();
System.out.println("testAsyncReturnInt()->线程名:" + Thread.currentThread().getName());

System.out.println("testAsyncReturnInt() ->消耗时间:" + (System.currentTimeMillis() - startTime));
return new AsyncResult<>(1);
}

@Override
public Future<Map<String, String>> testAsync() {
long startTime = System.currentTimeMillis();
this.sleep();
System.out.println("testAsync()->线程名:" + Thread.currentThread().getName());

Map<String,String> resMap = new HashMap<>(INIT_SIZE);
resMap.put("name","zhouhouxing");
resMap.put("age","18");
System.out.println("testAsync() ->消耗时间:" + (System.currentTimeMillis() - startTime));

return new AsyncResult<>(resMap);
}

// 休眠一秒钟模拟查询 DB 或者其他系统消耗时间
private void sleep(){
try {
TimeUnit.SECONDS.sleep(SlEEP_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

第四步:测试无返回值接口

@GetMapping("/testAsyncNoReturns")
@ApiOperation(value = "测试异步无返回值")
public ResponseBean testAsyncNoReturns(){
long startTime = System.currentTimeMillis();
testService.testAsyncNoReturns();

System.out.println("testAsyncNoReturns() 主线程执行时间:"+ (System.currentTimeMillis() - startTime));
return new ResponseBean(Constant.errCode.OK,"","无返回值");
}

注:这里时间单位是毫秒(可以发现主线程消耗7毫秒,异步处理线程消耗1秒秒钟)

5、异步请求需要返回值的的一定要使用 Future 包装否则取不到返回值。
我们这里使用了 spring 封装的 AsyncResult 类作为返回VO, 他实现了ListenableFuture 而 ListenableFuture 又继承自 Future。
下面 Integer 是未使用 Future 包装所以取值为NULL

6、正常请求多个有返回值的 异步方法。

 @GetMapping("/testAsync")
@ApiOperation(value = "测试异步有返回值")
public ResponseBean testAsync() throws ExecutionException, InterruptedException {
long startTime = System.currentTimeMillis();

Future<Map<String, String>> future = testService.testAsync();
Future<Integer> integer = testService.testAsyncReturnInt();

System.out.println("===> map 返回值结果:" + future.get());
System.out.println("===> integer 返回值结果:" + integer.get());

System.out.println("testAsync() 主线程执行时间:"+ (System.currentTimeMillis() - startTime));
return new ResponseBean(Constant.errCode.OK,"","有返回值");
}



注意:
如果是在同一个类中 调用其本类的异步方法将不起作用【因为触发不了springboot的代理】springboot 大部分都是基于 AOP 实现的

这里只是作为简单的使用示例。
当然里面更好玩的操作还要再去深入了解。