2013-04-12 38 views
26

我遇到过EntityUtils.consume(httpEntity);,我不确定它确实做了什么。作者为什么使用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);finally块将关闭连接和垃圾收集器将采取的httpEntity照顾?

回答

31

这真的归结为是一个“好公民”(和真正了解的HTTPClient接口的合同)。 什么EntityUtils.consume将要做的是发布由httpEntity,基本上意味着释放任何基础流,并给予Connection对象返回到其池(在的情况下你的连接管理器是一个多线程的一个)或释放连接管理器,使持有的所有资源,它可以处理下一个请求。

如果你不消耗entity,会发生什么真的取决于finally从句什么“关停连接管理器”的意思。它会关闭悬而未决的流/连接还没有被发回池吗?我不确定它会以合约的方式做到这一点(虽然我认为它的实施方式)。如果没有,那么你可能会泄露系统资源(套接字等)。 发生什么也取决于Entity对象的可能终结方法,如果它可能(如果它被执行)释放它的资源,再次,不确定它是否在实体的合同中这样做。

让我们假设针对该ConnectionManager实际上关闭所有未决资源正常,当它关闭一分钟。你还需要消费实体吗?我说是的,因为从现在起一个月,有人会修改你的代码,并在同一个try/finally块中进行第二次HTTP调用,并且可能无法这样做,因为你没有按照你应有的方式释放资源(例如,如果您的客户端位于单个连接池中,而不释放第一个连接会导致第二个连接失败)。

所以我的观点是:实体是资源,而不是在需要的时候,他们的资源应该被释放。在以后的日子里指望别人给你释放它们可能会在将来伤害你。原作者可能会考虑这些方面。作为一个方面说明,请注意,你写的实现实际上会消耗读者直到基础流的末尾,所以消费调用实际上什么都不做,但在我看来,这是一个实现细节(从我的头顶开始,一旦响应流被完全读取,连接对象将自动释放/发送回http客户端中的池)。 还要注意,如果使用API​​提供的ResponseHandler机制,则所有这些Consume逻辑也会从您抽象出来。 最后,API不保证response.getEntity永远不会返回null,因此您应该检查以避免NullPointerException

相关问题