【问题标题】:Why did the author use EntityUtils.consume(httpEntity);?为什么作者使用EntityUtils.consume(httpEntity);?
【发布时间】:2013-04-12 10:31:09
【问题描述】:

我遇到过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();
}

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

【问题讨论】:

    标签: java apache-httpclient-4.x


    【解决方案1】:

    真正归结为“好公民”(并且真正了解HTTPClient 接口的合同)。 EntityUtils.consume 将释放httpEntity 持有的所有资源,这实质上意味着释放任何底层 Stream 并将 Connection 对象返回其池(如果您的连接管理器是多线程的)或释放连接管理器以便它可以处理下一个请求。

    如果你不使用entity,会发生什么实际上取决于finally 子句中“关闭连接管理器”的含义。它会关闭尚未发送回池的待处理流/连接吗?我不确定它会以合同方式做到这一点(尽管我认为在实施方面确实如此)。如果没有,那么您可能正在泄漏系统资源(套接字等)。 发生的情况也可能取决于 Entity 对象的可能最终确定方法,该方法可能(如果它被执行)释放其资源,同样,不确定它是否在实体的合同中这样做。

    让我们假设ConnectionManager 在关闭时实际上优雅地关闭了所有挂起的资源。你还需要消耗实体吗?我说是的,因为一个月后,有人会修改你的代码并在同一个 try/finally 块中进行第二次 HTTP 调用,并且可能无法这样做,因为你没有以应有的方式释放资源(例如,如果您的客户端位于单个连接池上,不释放第一个连接将导致第二次调用失败)。

    所以我的观点是:实体是资源,在不需要时应该释放资源。指望其他人在以后为您释放它们可能会在将来伤害您。原作者可能就是这么想的。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-20
      • 1970-01-01
      • 1970-01-01
      • 2020-09-01
      • 2018-01-05
      相关资源
      最近更新 更多