异步回调调用同步化改造:移除Thread.sleep()实现实时响应
改造方案:移除Thread.sleep,用异步回调返回API响应
你的当前实现用同步轮询+Thread.sleep()的方式等待第三方响应,这会严重浪费线程资源——每个请求都会占着一个线程空等,高并发场景下很容易把线程池耗光。下面给你一套基于Spring异步响应机制的改造方案,完全去掉轮询和sleep,用回调实时返回结果。
核心思路
利用Spring的DeferredResult实现异步请求处理:
- 客户端发起请求时,API创建一个
DeferredResult并暂存,立刻返回挂起的响应(Spring会释放当前线程) - 第三方回调触发时,直接把响应结果设置到对应的
DeferredResult中,Spring会自动完成响应并返回给客户端
具体改造步骤
1. 改造ClientFixApp组件
把原来存储响应字符串的Map换成存储DeferredResult<String>的Map,让回调能直接关联到对应的请求:
@Component public class ClientFixApp { // 用ConcurrentHashMap保证多线程下的安全操作 private final Map<String, DeferredResult<String>> deferredResultMap = new ConcurrentHashMap<>(); // 注册DeferredResult,供API调用绑定请求 public void registerDeferredResult(String requestId, DeferredResult<String> deferredResult) { // 设置超时处理:第三方超时未响应时返回错误 deferredResult.onTimeout(() -> { deferredResult.setErrorResult(ResponseEntity.status(HttpStatus.REQUEST_TIMEOUT).body("Request timeout waiting for third-party response")); // 超时后清理Map,避免内存泄漏 deferredResultMap.remove(requestId); }); // 请求完成后(成功/失败)自动清理Map deferredResult.onCompletion(() -> deferredResultMap.remove(requestId)); deferredResultMap.put(requestId, deferredResult); } // 第三方库回调方法,收到响应时触发 @Override public void onResponse(String requestId, String jsonMsg) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType { DeferredResult<String> deferredResult = deferredResultMap.get(requestId); if (deferredResult != null) { // 设置成功响应,Spring会自动返回给客户端 deferredResult.setResult(ResponseEntity.ok(jsonMsg)); } } }
注:原代码中
onResponse方法参数只写了requestId,但实际要存入jsonMsg,这里假设你的回调方法能拿到响应内容,可根据实际参数调整。
2. 改造API方法
把同步响应改成返回DeferredResult<ResponseEntity<String>>,彻底移除轮询和sleep:
@GetMapping public DeferredResult<ResponseEntity<String>> getData(@RequestBody String requestId) throws SessionNotFound { // 创建DeferredResult,设置超时时间(示例为30秒,可根据业务调整) DeferredResult<ResponseEntity<String>> deferredResult = new DeferredResult<>(30000L); // 绑定请求ID和DeferredResult,等待回调 clientFixApp.registerDeferredResult(requestId, deferredResult); // 提交请求到第三方 dataService.get(requestId); // 直接返回DeferredResult,Spring会处理异步响应逻辑 return deferredResult; }
3. 调整DataService(无需大改)
原来的DataService只需保证正确提交请求到第三方即可:
@Service public class DataService { @Autowired private ClientApp clientApp; public void get(String requestId) throws SessionNotFound { // 提交请求到第三方,响应会通过ClientFixApp的onResponse回调返回 send(requestId); } }
方案优势
- 完全移除
Thread.sleep()和轮询逻辑,响应更实时 - 异步处理不占用线程空等,大幅提升系统并发能力
- 自带超时处理,避免请求无限挂起
- 自动清理资源,不会造成内存泄漏
额外注意事项
- 确保
ClientFixApp的onResponse方法线程安全(已用ConcurrentHashMap保证) - 根据业务场景合理调整超时时间,避免过短或过长
- 如果第三方可能重复回调同一requestId,可在设置结果后立刻移除Map条目,避免重复处理
内容的提问来源于stack exchange,提问作者thejavaguy




