初识spring-boot异步编程

Posted 码农基础

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初识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 实现的

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


以上是关于初识spring-boot异步编程的主要内容,如果未能解决你的问题,请参考以下文章

初识async函数

初识Generator和Async函数

解决spring-boot启动中碰到的问题:Cannot determine embedded database driver class for database type NONE(转)(代码片段

初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段

初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段

使用Task.Wait而不是等待异步编程