2013-04-12 6 views
26

Ich bin auf EntityUtils.consume(httpEntity); gestoßen und ich bin mir nicht sicher, was es wirklich tut.Warum hat der Autor EntityUtils.consume (httpEntity) verwendet?

Zum Beispiel:

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

Warum der Autor in EntityUtils.consume(httpEntity); gelegt hat, wenn der finally Block wird die Verbindung und Garbage Collector schließen kümmern httpEntity?

Antwort

31

Es läuft wirklich darauf hinaus, ein "guter Bürger" zu sein (und wirklich die Verträge von HTTPClient Schnittstellen zu kennen). Was EntityUtils.consume tun wird, ist die Freigabe aller Ressourcen von httpEntity, was im Wesentlichen die Freigabe eines zugrundeliegenden Streams und das Zurückgeben des Connection-Objekts an seinen Pool bedeutet (falls Ihr Verbindungsmanager ein Multithread ist) oder den Verbindungsmanager freizugeben kann die nächste Anfrage bearbeiten.

Wenn Sie die entity nicht konsumieren, hängt das, was passiert, davon ab, was "Herunterfahren des Verbindungsmanagers" in der finally-Klausel bedeutet. Werden anstehende Streams/Verbindungen, die nicht zurück in den Pool gesendet wurden, geschlossen? Ich bin mir nicht sicher, ob es das vertraglich tun wird (obwohl ich denke, dass es das tut). Wenn dies nicht der Fall ist, können Systemressourcen (Sockets usw.) verloren gehen. Was passiert, kann auch von einer möglichen Finalisierungsmethode des Entity-Objekts abhängen, das (falls es überhaupt ausgeführt wird) seine Ressourcen freigibt, wiederum nicht sicher, ob es im Vertrag der Entität ist, dies zu tun.

Nehmen wir einmal an, dass die ConnectionManager tatsächlich alle ausstehenden Ressourcen ordnungsgemäß schließt, wenn es heruntergefahren wird. Müsstest du die Entity noch konsumieren? Ich sage ja, denn in einem Monat wird jemand Ihren Code ändern und einen zweiten HTTP-Aufruf im selben try/finally-Block machen und kann dies möglicherweise nicht tun, weil Sie die Ressourcen nicht so freigegeben haben, wie Sie sollten (zB wenn Ihr Client befindet sich in einem einzigen Verbindungspool. Wenn Sie die erste Verbindung nicht freigeben, wird ein zweiter Anruf fehlschlagen.

Also mein Punkt ist: Entitäten sind Ressourcen, und Ressourcen sollten freigegeben werden, wenn sie nicht benötigt werden. Sich auf andere zu verlassen, um sie zu einem späteren Zeitpunkt für dich zu befreien, kann dich in der Zukunft verletzen. Der ursprüngliche Autor könnte in diese Richtung gedacht haben.

Beachten Sie, dass die Implementierung, die Sie geschrieben haben, tatsächlich den Reader bis zum Ende des zugrundeliegenden Streams verbraucht, so dass der Consumer-Aufruf tatsächlich gar nichts tut, aber meiner Meinung nach ist dies ein Implementierungsdetail (Aus der Spitze meines Kopfes, sobald ein Antwortstrom vollständig gelesen wurde, wird das Verbindungsobjekt automatisch in den Pool im http-Client freigegeben/zurückgesendet). Beachten Sie auch, dass all diese Consume-Logik auch von Ihnen abstrahiert wird, wenn Sie den ResponseHandler-Mechanismus verwenden, den die API bietet. Schließlich garantiert die API nicht, dass response.getEntity niemals Null zurückgibt, also sollten Sie dies überprüfen, um NullPointerException zu vermeiden.

Verwandte Themen