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

Java中重复调用HTTP服务发JSON请求获响应遇阻

解决HttpURLConnection重复调用时卡在getInputStream()的问题

我看你遇到的问题很典型——第一次调用solveInstance()访问本地scheduler服务完全正常,但第二次就卡在getInputStream()这一行,程序直接僵住,既不报错也没输出。这种情况十有八九是HTTP连接资源没有正确释放导致的,咱们一步步来分析和解决。

首先先还原你的核心代码场景:

public static void solveInstanceSet(String instanceSetName) { // run each instance in an Instance Set
 try { // get the instanceSet File
 File instanceSet = new File(instanceSetName);
 Scanner scanner = new Scanner(instanceSet);
 // solve each instance in the file
 while(scanner.hasNext()) {
 String instanceName = scanner.nextLine();
 solveInstance(instanceName);
 }
 } catch(IOException e) {
 System.out.println("Exception: Cannot read the File contains the Instances to run!");
 }
}
public static void solveInstance(String instanceName){ // solve a problem instance
 try{
 String query_url = "http://localhost:8807/scheduler";
 // read Request to a JSON Object
 JSONParser parser = new JSONParser();
 JSONObject request = (JSONObject) parser.parse(new FileReader(instanceName));
 // open connection
 URL url = new URL(query_url);
 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 conn.setConnectTimeout(5000);
 conn.setRequestProperty("Content-Type", "application/json");
 // 核心逻辑:发送请求、获取响应的代码未正确释放资源
 } catch(Exception e) {
 // 异常处理
 }
}

问题根源

HttpURLConnection默认启用了HTTP Keep-Alive(连接复用),第一次请求完成后,连接会被放到连接池里供后续请求复用。但如果你的代码没有正确关闭请求的输出流、响应的输入流(甚至错误流),这个连接就不会被释放回连接池。当连接池里的连接都被占用且没有释放时,第二次请求就会阻塞在获取连接/输入流的步骤,也就是你看到的卡在getInputStream()的情况。

解决方案:强制确保所有资源被正确关闭

解决的核心就是在每次请求结束后,不管成功还是失败,都要关闭所有相关的流资源,最好用Java的try-with-resources语法,它会自动帮你关闭实现了AutoCloseable接口的资源,避免手动遗漏。

修改后的solveInstance()方法示例:

public static void solveInstance(String instanceName){ // solve a problem instance
    try{
        String query_url = "http://localhost:8807/scheduler";
        // 读取请求JSON
        JSONParser parser = new JSONParser();
        JSONObject request = (JSONObject) parser.parse(new FileReader(instanceName));
        
        URL url = new URL(query_url);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        try {
            conn.setConnectTimeout(5000);
            conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            // 发送JSON请求体必须设置为POST方法并允许输出
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            
            // 发送JSON请求体,用try-with-resources自动关闭OutputStream
            try (OutputStream os = conn.getOutputStream()) {
                byte[] requestBytes = request.toJSONString().getBytes(StandardCharsets.UTF_8);
                os.write(requestBytes, 0, requestBytes.length);
            }
            
            // 获取响应码,判断是成功还是错误
            int responseCode = conn.getResponseCode();
            // 不管成功还是错误,都要获取对应的流并关闭
            try (InputStream is = responseCode >= 200 && responseCode < 300 
                    ? conn.getInputStream() 
                    : conn.getErrorStream()) {
                if (is != null) {
                    // 读取响应内容(可根据你的需求调整处理逻辑)
                    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
                    StringBuilder responseBuilder = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        responseBuilder.append(line);
                    }
                    System.out.println("处理实例 " + instanceName + " 完成,响应:" + responseBuilder.toString());
                }
            }
        } finally {
            // 手动断开连接,确保资源被彻底释放(即使流已关闭,这一步更保险)
            conn.disconnect();
        }
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("处理实例 " + instanceName + " 时发生异常");
    }
}

额外注意点

  1. 处理错误流:如果服务端返回4xx/5xx的错误码,直接调用getInputStream()会抛出IOException,这时候必须用getErrorStream()获取错误响应,并且也要关闭这个流,否则连接还是不会释放。
  2. try-with-resources的使用:所有实现了AutoCloseable的资源(比如OutputStream、InputStream)都应该放在try-with-resources里,不用手动调用close(),避免因为异常导致close被跳过。
  3. 显式设置请求方法:因为要发送JSON请求体,必须设置conn.setRequestMethod("POST")和conn.setDoOutput(true),否则无法发送请求体。

这样修改后,每次请求完成后所有资源都会被正确释放,连接池里的连接可以正常复用,第二次及以后的调用就不会卡住了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:44:43