You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

异步回调调用同步化改造:移除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()和轮询逻辑,响应更实时
  • 异步处理不占用线程空等,大幅提升系统并发能力
  • 自带超时处理,避免请求无限挂起
  • 自动清理资源,不会造成内存泄漏

额外注意事项

  • 确保ClientFixApponResponse方法线程安全(已用ConcurrentHashMap保证)
  • 根据业务场景合理调整超时时间,避免过短或过长
  • 如果第三方可能重复回调同一requestId,可在设置结果后立刻移除Map条目,避免重复处理

内容的提问来源于stack exchange,提问作者thejavaguy

火山引擎 最新活动