最近遇到一个前端接口需要批量请求接口,担心超时,所以使用批量异步的请求方式
//批量构造请求
for (ProductInfoParam productInfoParam : list) {
CompletableFuture<FlashLiveInfo> tmp = CompletableFuture.supplyAsync(() -> {
try {
String url = String.format(flashLiveUrl,productInfoParam.getProductCode(),productInfoParam.getMerchantCode(),"","");
//异步请求数据
String jsonStr = httpClientUtil.executeGetNoProxy(url);
JsonNode res = JacksonUtil.INSTANCE.getObjectMapper().readTree(jsonStr);
String result = res.get("result").asText();
//请求成功
if (StringUtils.equals("0", result)) {
JsonNode data = res.get("data");
return JacksonUtil.INSTANCE.getObjectMapper().convertValue(data, FlashLiveInfo.class);
} else {
String msg = res.get("msg").asText();
String errorCode = res.get("errorCode").asText();
LOG.error("queryFlashLiveInfo query msg ={} ,errorCode={}", msg, errorCode);
}
} catch (HttpClientException e) {
throw new RuntimeException("查询接口异常,e={}", e);
} catch (IOException e) {
throw new RuntimeException("查询解析接口返回异常,e={}", e);
}
//这里要返回一个值,这里在后面采坑了
return null;
}, ThreadPool.getFrontExecutor()).whenComplete((result,throwable)->{
//任务完成时执行。用list存放任务的返回值
if (result != null && result.getRecordId()!=null) {
resultList.add(result);
}
//触发异常
if (throwable != null) {
LOG.error("completableFuture1 error:{}", throwable);
}
});
futureList.add(tmp);
}
//
try {
//多个任务
CompletableFuture[] futureArray = futureList.toArray(new CompletableFuture[0]);
//将多个任务,汇总成一个任务,总共耗时不超时10秒
CompletableFuture.allOf(futureArray).get(10, TimeUnit.SECONDS);
} catch (Exception e) {
LOG.error("CompletableFuture.allOf Exception error e={}", e);
}
futureArray数组 一定不能有null 元素,否则并不是等待10s,而是把NPE报错时已经跑完的任务直接返回了。我在生产就遇到了 ,所以建议 new CompletableFuture[0],不用担心越界,实际上会动态填充,但是如果数组过大,。后面的也会自动填写null ,还是会遇到我上面所说的问题。我当初写new CompletableFuture[20],预计是20个商品发送请求。结构有的请求报错,我就默认填写null到数组中了
CompletableFuture[] futureArray = futureList.toArray(new CompletableFuture[0]);