1: 线程池
1.1 自定义线程池
在项目中建议自定义一个线程池
@Bean
public ThreadPoolExecutor threadPoolExecutor() {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2,
5,
2,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
return executor;
}
1.2参数详解
参数一:corePoolSize:线程池中的常驻核心线程数,在创建了线程池后,当有请求任务来之后,就会安排池中的线程去执行请求任务,可以理解为今日当值线程,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放入到缓存队列当中.
参数二:maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值大于等于1
参数三:keepAliveTime:多余的空闲线程存活时间,当空间时间达到keepAliveTime值时,多余的线程会被销毁直到只剩下corePoolSize个线程为止默认情况下:只有当线程池中的线程数大于corePoolSize时keepAliveTime才会起作用,知道线程中的线程数不大于corepoolSIze,
参数四:unit:keepAliveTime的单位
参数五:workQueue:任务队列,被提交但尚未被执行的任务.
参数六:threadFactory:表示生成线程池中工作线程的线程工厂,用户创建新线程,一般用默认即可
参数七:handler:拒绝策略,表示当线程队列满了并且工作线程大于等于线程池的最大显示 数(maxnumPoolSize)时如何来拒绝.
2: 使用feign远程调用
// 获取商品详细信息
@Override
public Map<String, Object> getItemById(Long skuId, Long userId) {
Map<String, Object> resMap = new HashMap<String, Object>();
//1: 根据skuId 获取商品详细信息
CompletableFuture<SkuInfoVo> skuInfoVoFuture = CompletableFuture.supplyAsync(() -> {
// 使用多线程方式实现远程接口异步调用
SkuInfoVo skuInfoVo = productFeignClient.getSkuInfo(skuId);
resMap.put("skuInfoVo", skuInfoVo);
return skuInfoVo;
}, threadPoolExecutor);
//2: 获取用户的商品优惠卷信息
CompletableFuture<Void> activityFuture = CompletableFuture.runAsync(() -> {
//远程调用获取优惠卷
Map<String, Object> activityMap = activityFeignClient.findActivityAndCoupon(skuId, userId);
resMap.putAll(activityMap);
},threadPoolExecutor);
//3: 更新商品热度 , 每次浏览详情热度修改
CompletableFuture<Void> serviceFuture = CompletableFuture.runAsync(() -> {
searchFeignClient.getHotProduct();
},threadPoolExecutor);
//将任务组合,
CompletableFuture.allOf(
skuInfoVoFuture,
activityFuture,
serviceFuture
).join();
return resMap;
}
2.1: 远程调用不同服务
/**
* 使用openfeign实现调用search服务的接口
*/
@FeignClient(value = "service-search")
public interface SearchFeignClient {
@GetMapping("/api/search/sku/inner/findHotSkuList")
List<SkuEs> getHotProduct() ;
}
//商品详细信息
@GetMapping("/admin/activity/activityInfo/findActivityAndCoupon/{skuId}/{userId}")
public Map<String, Object> findActivityAndCoupon(@PathVariable("skuId") Long skuId,
@PathVariable("userId") Long userId);
@GetMapping("/api/product/inner/getSkuInfo/{skuId}")
public SkuInfoVo getSkuInfo(@PathVariable("skuId") Long skuId);
2.2: 多线程的join()方法
join() 的作用:让“主线程”等待“子线程”结束之后才能继续运行。
代码中创建了三个子线程 skuInfoVoFuture,activityFuture,serviceFuture ,当三个子线程的业务都执行完, 这个线程才能返回, 使用join()能够避免子线程未执行完,主线程就结束.