CompletableFuture
Java 中 java.util.concurrent 包中的一个类,它提供了一个用于异步编程的强大工具。它可以用来表示一个计算的结果,该计算将在将来的某个时间完成,并且可以通过各种方法来处理当前计算的结果,例如等待计算完成、应用函数来处理结果、组合多个 CompletableFuture 实例,等等。它使得在进行并行或异步操作时更加容易处理异常情况、经济地使用线程以及简化代码的编写。
需求:接口响应时间不确定 需要定义一个时间控制响应时间 设置响应时间和程序等待时间不对等
demo
public String getAnswer(String question, Long dialogId) {
String userId = tokenService.getLoginUser().getUserId();
LocalDateTime now = LocalDateTime.now();
String key = "msgId:" + userId + ":" + now;
ExecutorService executor = Executors.newSingleThreadExecutor();
CompletableFuture<HttpResponse> future = CompletableFuture.supplyAsync(() -> {
return HttpRequest.post("********")
.timeout(600000)
.form("message", question)
.execute();
}, executor);
//异步等待响应结果 保存到数据库
future.thenAcceptAsync(message -> {
synchronized (key) {
//响应数据 更具msgID判断是否插入还是更新
Long msgId = redisCache.getCacheObject(key);
msgId = saveToDatabase(message.body(), dialogId, now, userId, msgId);
redisCache.setCacheObject(key, msgId, 1, TimeUnit.MINUTES);
executor.shutdown();
}
}, executor).exceptionally(e -> {
e.printStackTrace();
executor.shutdown(); // shutdown the executor if an exception occurs
return null;
});
//响应最长等待30秒 没有返回先插入默认数据
try {
HttpResponse message = future.get(30, TimeUnit.SECONDS);
return message.body();
} catch (TimeoutException e) {
synchronized (key) {
Long msgId = redisCache.getCacheObject(key);
if (msgId == null) {
//ai接口未响应 存入默认数据
msgId = saveToDatabaseAwait("反应的时间比预期的要长。请稍后刷新试试。", dialogId, now, userId);
redisCache.setCacheObject(key, msgId, 1, TimeUnit.MINUTES);
}
return "响应时间比预期的要长。请稍后刷新试试。";
}
} catch (Exception e) {
// Handle other exceptions
e.printStackTrace();
return "An error occurred.";
}
}
public Long saveToDatabase(String aiResp, Long dialogId, LocalDateTime qTime, String userId, Long id) {
AiDialogMsg aiDialogMsg = AiDialogMsg.builder().build();
if (id == null) {
//保存AI消息
aiDialogMsg = AiDialogMsg.builder().dialogId(dialogId)
.content(aiResp)
.createTime(qTime)
.id(id)
.userId(userId)
.isAiResp(1)
.build();
aiDialogMsgService.save(aiDialogMsg);
} else {
//更新内容
aiDialogMsg = AiDialogMsg.builder()
.content(aiResp)
.id(id)
.build();
aiDialogMsgService.updateById(aiDialogMsg);
}
return aiDialogMsg.getId();
}
//未得到响应结果 插入等待数据
public Long saveToDatabaseAwait(String aiResp, Long dialogId, LocalDateTime qTime, String userId) {
AiDialogMsg aiDialogMsg = AiDialogMsg.builder().build();
//保存默认AI消息
aiDialogMsg = AiDialogMsg.builder().dialogId(dialogId)
.content(aiResp)
.createTime(qTime)
.userId(userId)
.isAiResp(1)
.build();
aiDialogMsgService.save(aiDialogMsg);
return aiDialogMsg.getId();
}