2013-04-12 14 views
26

Natknąłem EntityUtils.consume(httpEntity); i nie jestem pewien, co tak naprawdę robi.Dlaczego autor użył EntityUtils.consume (httpEntity) ;?

Na przykład:

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(); 
} 

Dlaczego autor umieścić w EntityUtils.consume(httpEntity); gdy blok finally będzie zamknąć połączenie i śmieciarza zajmie httpEntity?

Odpowiedz

31

To naprawdę sprowadza się do bycia „dobrym obywatelem” (i naprawdę znając umów HTTPClient interfejsów). Co EntityUtils.consume zrobi to uwolnienia wszystkich zasobów posiadanych przez httpEntity, która zasadniczo zakłada puszczania wszelkich podstawowych Stream i dających obiektu Connection z powrotem do puli (w przypadku menedżer połączenie to wielowątkowy jeden) lub uwolnienie menedżer połączeń, tak aby może przetworzyć następne żądanie.

Jeśli nie zużyjesz entity, to, co się dzieje naprawdę, zależy od tego, co oznacza "zamknięcie menedżera połączeń" w klauzuli finally. Czy zamknie oczekujące strumienie/połączenia, które nie zostały wysłane z powrotem do puli? Nie jestem pewien, czy to zrobi w umowie (chociaż myślę, że to w praktyce). Jeśli nie, możesz przeciekać zasoby systemowe (gniazda itp.). Co się dzieje, może również zależeć od ewentualnej finalizacji metody obiektu podmiotu, który może (jeśli zostanie zrealizowane w ogóle) uwalniać swoje zasoby, znowu, nie jestem pewien, że jest w umowie jednostki to zrobić.

Załóżmy na chwilę, że ConnectionManager faktycznie zamyka wszystkie oczekujące zasobów wdzięcznie, gdy wyłączy się. Czy nadal będziesz potrzebował konsumować Entity? Mówię tak, ponieważ za jeden miesiąc ktoś zmieni twój kod i wykona drugie połączenie HTTP w tym samym bloku try/finally i może nie być w stanie tego zrobić, ponieważ nie uwolniłeś zasobów w sposób, w jaki powinieneś (np. klient znajduje się w pojedynczej puli połączeń, a uwolnienie pierwszego połączenia nie spowoduje niepowodzenia drugiego połączenia).

Więc chodzi mi o to: Podmioty są środki i zasoby powinny zostać uwolnione, gdy nie są potrzebne. Liczenie na innych, aby uwolnić ich dla ciebie w późniejszym czasie, może cię zranić w przyszłości. Pierwotny autor mógł pomyśleć wzdłuż tych linii.

Na marginesie zauważ, że wprowadzona przez ciebie implementacja rzeczywiście pochłonie czytelnika do końca strumienia bazowego, więc wywołanie funkcji konsumowania w rzeczywistości nic nie da, ale moim zdaniem jest to szczegół implementacji (ze szczytu mojej głowy, po całkowitym odczytaniu strumienia odpowiedzi, obiekt połączenia jest automatycznie zwalniany/wysyłany z powrotem do puli w kliencie http). Należy również zauważyć, że cała ta logika konsumowania jest również pobierana z użytkownika, jeśli używasz mechanizmu ResponseHandler, który oferuje interfejs API. Wreszcie interfejs API nie gwarantuje, że response.getEntity nigdy nie zwróci wartości null, więc powinieneś to sprawdzić, aby uniknąć NullPointerException.

Powiązane problemy