使用executor.execute(Runnable task)方法
思路:事先定义一个存放结果的集合(必须是线程安全的集合),作为参数传到多线程任务中,每个任务执行后把需要返回的结果放在集合中。
这样在执行完成后就可以访问这个集合拿到返回值。但是还有一个问题:
怎么保证当我们访问集合时任务都已经执行完成保证不会丢失某一条任务的执行结果呢????
必须是线程安全的集合所以这里就要使用java.util.concurrent包下的CountDownLatch类,保证多线程全部执行完毕后再进行后续操作。实现的原理其实就是计数器类型的同步锁。
new CountDownLatch(50):初始化数量
latch.countDown():任务执行完成,数量减1
latch.await();等待,不断检测数量是否为0,为零是执行后面的操作
final CountDownLatch latch=new CountDownLatch(3);//定义多线程数量,一般就是任务数量
threadPoolTaskExecutor.execute(()->{
try {
Thread.sleep(1);
//商品搜索结果
List<ProductHomeSearchVO> products = this.siteSearchGoods(keyWord);
log.info("HomeServiceImpl.siteSearch:商品搜索结果{}条",products==null?"0":products.size());
//商品VO
resultMap.put(SearchStatusEnum.Insurance_Products.getCode(), products);
} catch (InterruptedException e) {
log.info("查询商品报错",e.getMessage());
}finally{
latch.countDown();//每个任务执行完成后对数量进行减一操作
}
});
threadPoolTaskExecutor.execute(()->{
try {
Thread.sleep(1);
//保险知道搜索
PageInfo<NewsVO> knowledgePageInfo = new PageInfo<>();
this.queryNewsVOList(keyWord,knowledgePageInfo,SearchStatusEnum.Insurance_Knowledge.getCode());
//保险知道VO
synchronizedlist.addAll(knowledgePageInfo.getList());
resultMap.put(SearchStatusEnum.Insurance_Knowledge.getCode(), knowledgePageInfo);
} catch (InterruptedException e) {
log.info("查询保险知道",e.getMessage());
}finally{
latch.countDown();//每个任务执行完成后对数量进行减一操作
}
});
threadPoolTaskExecutor.execute(()->{
try {
Thread.sleep(1);
//保险服务搜索
PageInfo<NewsVO> servicePageInfo = new PageInfo<>();
this.queryNewsVOList(keyWord,servicePageInfo,SearchStatusEnum.Insurance_Service.getCode());
//保险知道VO
synchronizedlist.addAll(servicePageInfo.getList());
resultMap.put(SearchStatusEnum.Insurance_Service.getCode(), servicePageInfo);
} catch (InterruptedException e) {
log.info("查询保险服务",e.getMessage());
}finally{
latch.countDown();//每个任务执行完成后对数量进行减一操作
}
});
latch.await();//等待,不断检测数量是否为0,为零是执行后面的操作
//处理参数
if (null != resultMap.get(SearchStatusEnum.Insurance_Products.getCode()) &&
CollectionUtils.isNotEmpty((List<ProductHomeSearchVO>)resultMap.get(SearchStatusEnum.Insurance_Products.getCode()))){
List<ProductHomeSearchVO> productVo = (List<ProductHomeSearchVO>)resultMap.get(SearchStatusEnum.Insurance_Products.getCode());
homeSearchVO.setProducts(productVo);
}
if (null != resultMap.get(SearchStatusEnum.Insurance_Knowledge.getCode()) &&
CollectionUtils.isNotEmpty(((PageInfo<NewsVO>)resultMap.get(SearchStatusEnum.Insurance_Knowledge.getCode())).getList())){
PageInfo<NewsVO> knowledgePageInfo = (PageInfo<NewsVO> )resultMap.get(SearchStatusEnum.Insurance_Knowledge.getCode());
homeSearchVO.setKnowledgePageInfo(knowledgePageInfo);
}
if (null != resultMap.get(SearchStatusEnum.Insurance_Service.getCode()) &&
CollectionUtils.isNotEmpty(((PageInfo<NewsVO>)resultMap.get(SearchStatusEnum.Insurance_Service.getCode())).getList())){
PageInfo<NewsVO> servicePageInfo = (PageInfo<NewsVO> )resultMap.get(SearchStatusEnum.Insurance_Service.getCode());
homeSearchVO.setServicePageInfo(servicePageInfo);
}
//热门搜索记录
if (StringUtils.isNotBlank(keyWord) &&
(CollectionUtils.isNotEmpty(homeSearchVO.getProducts())
|| CollectionUtils.isNotEmpty(synchronizedlist))){
//热门搜索词汇量
Long count = redisService.zcard(FaceWebCommonConstants.POPULAR_SEARCHES);
if (count>-1 && count<11){
redisService.zinCrBy(FaceWebCommonConstants.POPULAR_SEARCHES, keyWord,1.0 );
}
redisService.set(FaceWebCommonConstants.POPULAR_SEARCHES+keyWord, JSONObject.toJSONString(homeSearchVO), 60*60);
}
log.info("homeSearchVO{}",JSON.toJSONString(homeSearchVO));
resultDTO.setData(homeSearchVO);