文章目录
线程池与异步任务
复习线程池
在项目中只使用线程池的方式,这种池化技术节省资源开销,能够控制资源
池化技术:事先准备好一些资源,要使用就去池子里拿,用完了要还到池子里去(重复利用)
- 实现复用,降低频繁创建,销毁资源的消耗
- 提高响应速度,提交任务时不用等待创建线程就能立即执行
- 方便管理,控制并发数
复习链接Java中的线程池
CompletableFuture 异步编排
启动异步任务
Runnable和Supplier都是函数式接口,所以可以使用lambda表达式
private static Executor executor = new ThreadPoolExecutor(5, 10,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
/**
* 测试启动异步任务
*/
private static void test1(){
//runAsync 无返回值异步任务
CompletableFuture.runAsync(() -> {
System.out.println("main start");
Integer sum = 0;
for (int i = 0; i < 100; i++) {
sum += i;
}
System.out.println(sum);
System.out.println("main end");
}, executor);
//supplyAsync 有返回值异步任务
CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
System.out.println("main start");
Integer sum = 0;
for (int i = 0; i < 100; i++) {
sum += i;
}
System.out.println(sum);
System.out.println("main end");
return sum;
}, executor);
Integer integer = null;
try {
integer = supplyAsync.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("sum:"+integer);
}
完成回调和异常感知
-
回调感知
whenComplete/whenCompleteAsync
(带有Async则是继续异步执行)- 第一个参数是结果,第二个参数是异常信息
-
异常感知
exceptionally
- 参数是异常信息
- 发生异常才会执行
- 发生异常时相比与whenComplete,exceptionally可以返回默认值
//supplyAsync 有返回值异步任务
CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
System.out.println("main start");
Integer sum = 100/10;
System.out.println("main end");
return sum;
}, executor).whenComplete((result,exception)->{
System.out.println("结果:"+result+";异常:"+exception);
}).exceptionally(exception->{
//有异常返回默认值
return 100;
});
Integer integer = null;
try {
integer = supplyAsync.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("sum:"+integer);
未发生异常结果
发生异常结果
异步任务完成时的处理
在异步任务完成后使用handler进行处理
可以把handler看作回调感知和异常感知的结合
CompletableFuture<Integer> supplyAsync = CompletableFuture.supplyAsync(() -> {
System.out.println("main start");
Integer sum = 100 / 0;
return sum;
}, executor)
// .whenComplete((result,exception)->{
// System.out.println("结果:"+result+";异常:"+exception);
// }).exceptionally(exception->{
// System.out.println("exception:"+exception);
// //有异常返回默认值
// return 100;
// });
.handle((result, exception) -> {
if (result != null) {
System.out.println("结果:" + result);
return result;
}
if (exception != null) {
System.out.println("异常:" + exception);
return 100;
}
return 0;
});
Integer integer = null;
try {
integer = supplyAsync.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("sum:" + integer);
System.out.println("main end");
两任务组合
两组任务完成后要执行的任务
设置两组任务完成后要执行的任务
runAfterBoth(Async)
:无参数无返回值
thenAcceptBoth(Async)
:参数是任务结果,无返回值
thenCombine(Async)
参数是任务结果,有返回值
两组任务任一任务完成后要执行的任务
这个和上面类似,只是满足条件从两组任务都完成变成了任一任务完成
runAfterEitherAsync
无参数无返回值
acceptEitherAsync
参数是完成任务的结果,无返回值
applyToEitherAsync
参数为完成任务的结果,有返回值
多任务组合
allof
等待多任务完成
anyof
等待任一任务完成
项目整合异步任务
1.编写线程池配置文件类
@ConfigurationProperties(prefix = "mall.thread")
@Component
@Data
public class ThreadPoolConfigProperties {
private Integer maxSize;
private Integer coreSize;
private Integer keepAliveTime;
}
application.properties中设置值
mall.thread.maxSize=20
mall.thread.coreSize=5
mall.thread.keepAliveTime=20
2.导入依赖
<!-- 填写配置文件自动提示的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
3.编写线程池组件
@Configuration
public class ThreadPoolConfig {
@Bean
public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) {
return new ThreadPoolExecutor(pool.getCoreSize(), pool.getMaxSize()
, pool.getKeepAliveTime(), TimeUnit.SECONDS, new LinkedBlockingQueue<>(5000),
Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
}
}
4.编写异步任务核心代码
@Autowired
ThreadPoolExecutor executor;
@Override
public SkuItemResultVo item(Long skuId) throws ExecutionException, InterruptedException {
SkuItemResultVo result = new SkuItemResultVo();
// 1.sku基本信息
CompletableFuture<SkuInfoEntity> infoFuture = CompletableFuture.supplyAsync(() -> {
SkuInfoEntity skuInfoEntity = baseMapper.selectById(skuId);
result.setInfo(skuInfoEntity);
return skuInfoEntity;
}, executor);
// 3.spu销售组合 (1完成后异步执行)
CompletableFuture<Void> saleFuture = infoFuture.thenAcceptAsync(res -> {
List<SkuItemSaleAttrVo> saleAttrVos = skuInfoService.getSaleAttrBySpuId(res.getSpuId());
result.setSaleAttr(saleAttrVos);
}, executor);
// 4.spu介绍 (1完成后异步执行)
CompletableFuture<Void> descFuture = infoFuture.thenAcceptAsync(res -> {
SpuInfoDescEntity desc = spuInfoDescService.getById(res.getSpuId());
result.setDesc(desc);
}, executor);
// 5.spu规格参数 (1完成后异步执行)
CompletableFuture<Void> attrFuture = infoFuture.thenAcceptAsync(res -> {
List<SpuItemAttrGroupVo> attrGroupVos = attrGroupService.getAttrGroupsWithAttrsBySpuId(res.getSpuId(), res.getCatalogId());
result.setGroupVos(attrGroupVos);
}, executor);
// 2.sku图片信息
CompletableFuture<Void> imagesFuture = CompletableFuture.runAsync(() -> {
List<SkuImagesEntity> images = skuImagesService.getListBySkuId(skuId);
result.setImages(images);
}, executor);
//等待所有任务执行完毕
CompletableFuture.allOf(imagesFuture, attrFuture, descFuture, saleFuture).get();
return result;
}