为什么作者使用EntityUtils.consume(httpEntity);?

2022-09-01 00:36:03

我遇到过,我不确定它到底做了什么。EntityUtils.consume(httpEntity);

例如:

try {

    //... some code

    HttpEntity httpEntity = httpResponse.getEntity();
    BufferedReader br = new BufferedReader(new InputStreamReader(http.Entity.getContent()));
    String line;
    while ((line = br.readLine())!= null) {
        System.out.println(line);
    }
    EntityUtils.consume(httpEntity);
} catch (Exception e) {
    //code
} finally { 
    httpClient.getConnectionManager().shutdown();
}

为什么作者在块将关闭连接和垃圾收集器将处理时放入?EntityUtils.consume(httpEntity);finallyhttpEntity


答案 1

它实际上归结为成为一个“好公民”(并且真正了解接口的合同)。要执行的操作是释放 持有的所有资源,这实质上意味着释放任何基础 Stream 并将 Connection 对象放回其池(在连接管理器是多线程连接管理器的情况下)或释放连接管理器,以便它可以处理下一个请求。HTTPClientEntityUtils.consumehttpEntity

如果不使用 ,则实际发生的情况实际上取决于 finally 子句中的“关闭连接管理器”的含义。它是否将关闭尚未发送回池的挂起流/连接?我不确定它会在合同上做到这一点(尽管在实现方面我认为它确实如此)。如果没有,则可能是泄漏了系统资源(套接字等)。发生的事情还可能取决于Entity对象的可能的终结方法,该方法可以(如果它被执行)释放其资源,同样,不确定它是否在实体的契约中执行此操作。entity

让我们假设一分钟,当它关闭时,它实际上会优雅地关闭所有挂起的资源。是否仍需要使用实体?我说是的,因为从现在起一个月后,有人会修改你的代码,并在同一个try/finally block中进行第二次HTTP调用,并且可能无法这样做,因为你没有以你应该的方式释放资源(例如,如果你的客户端在单个连接池上,不释放第一个连接会使第二个调用失败)。ConnectionManager

所以我的观点是:实体是资源,资源应该在不需要的时候被释放。指望别人在以后为你释放他们,可能会在未来伤害你。原作者可能沿着这些思路思考过。

作为旁注,请注意,您编写的实现实际上会消耗读取器直到底层流的末尾,因此消耗调用实际上根本不执行任何操作,但在我看来,这是一个实现细节(在我的头顶上,一旦响应流被完全读取, 连接对象会自动释放/发送回 http 客户端中的池)。另请注意,如果您使用 API 提供的 ResponseHandler mecanism,所有这些 Consume 逻辑也会从您那里抽象出来。最后,API 不保证永远不会返回 null,因此您应该检查以避免 。response.getEntityNullPointerException


答案 2

推荐