You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用OkHttp3发送Delete请求抛出java.io.InterruptedIOException问题求助

解决OkHttp3 Delete请求抛出java.io.InterruptedIOException: interrupted的问题

首先,从你的调用栈日志里能一眼抓到关键线索:这个Delete请求是在WebSocket的onClose回调方法里触发的!这就是问题的核心所在。

问题根源分析

Tomcat的WebSocket容器处理onClose回调时,用的是和WebSocket会话绑定的专属线程。当会话关闭流程走完后,这个线程会被容器中断甚至回收。而你的runDelete方法里用了OkHttp的同步execute()——这个方法会阻塞当前线程直到请求完成。当执行请求的线程(也就是WebSocket的回调线程)被容器中断时,OkHttp正在进行的IO操作就会抛出InterruptedIOException: interrupted异常。

简单说:你的网络请求和WebSocket回调线程的生命周期绑定死了,线程被干掉,请求自然中途夭折。

解决方案

有两种靠谱的解决方式,根据你的业务场景选:

1. 改用OkHttp异步请求(推荐)

把同步的execute()换成异步的enqueue(),让请求在OkHttp自己维护的线程池里执行,完全脱离WebSocket回调线程的生命周期。

修改你的请求方法:

public void runDeleteAsync(String url, String token, Object sendRequest, okhttp3.Callback callback) {
    try {
        RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), JSON.toJSONString(sendRequest));
        Request request = new Request.Builder()
                .url(url)
                .delete(requestBody)
                .addHeader("token", token)
                .build();
        httpClient.newCall(request).enqueue(callback);
    } catch (Exception e) {
        log.error("调用delete失败", e);
        callback.onFailure(null, e);
    }
}

然后在WebSocket的onClose里调用异步方法:

// 在你的WebSocketClientEndpoint.onClose方法中
runDeleteAsync(
    "你的目标URL",
    token,
    sendRequest,
    new okhttp3.Callback() {
        @Override
        public void onFailure(okhttp3.Call call, IOException e) {
            log.error("异步Delete请求失败", e);
        }

        @Override
        public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
            try (response) { // 自动关闭response资源
                if (response.isSuccessful()) {
                    String result = response.body().string();
                    // 这里处理请求结果
                } else {
                    log.error("Delete请求返回错误状态码: {}", response.code());
                }
            }
        }
    }
);

2. 用独立线程池执行同步请求

如果你的业务逻辑必须用同步请求,那就把请求放到你自己维护的线程池里执行,别用WebSocket的回调线程:

// 先定义一个全局的线程池(比如在Spring里用@Bean注入)
private ExecutorService requestThreadPool = Executors.newFixedThreadPool(5);

// 包装原有同步方法
public void runDeleteInSeparateThread(String url, String token, Object sendRequest) {
    requestThreadPool.submit(() -> {
        String result = runDelete(url, token, sendRequest); // 调用你原来的同步方法
        // 在这里处理返回结果
    });
}

然后在onClose里调用这个包装后的方法即可。

额外注意点

  • 务必保证OkHttpClient是全局单例的,不要每次请求都新建实例,否则会快速耗尽系统线程资源。
  • 检查你的OkHttpClient超时配置,虽然这次的异常不是超时导致的,但合理的超时设置能避免请求无意义地阻塞。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:12:45