2013-04-12 39 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

相關問題