45

私は遭遇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);タイミングを作成者が入力したのはなぜですか?finallyhttpEntity

4

1 に答える 1

60

HTTPClient要するに、「善良な市民」であること (そして、インターフェースの契約を本当に知っていること) です。によって保持されてEntityUtils.consumeいるすべてのリソースを解放しますhttpEntity。これは基本的に、基になるすべての Stream を解放し、Connection オブジェクトをそのプールに戻すことを意味します (接続マネージャーがマルチスレッドの場合)、または接続マネージャーを解放して、次のリクエスト。

を使用しない場合entity、どうなるかは、finally 句での「接続マネージャーのシャットダウン」の意味によって異なります。プールに送り返されていない保留中のストリーム/接続を閉じますか? 契約上それを行うかどうかはわかりません(ただし、実装に関してはそうすると思います)。そうでない場合は、システム リソース (ソケットなど) がリークしている可能性があります。何が起こるかは、(実行された場合) リソースを解放する可能性がある Entity オブジェクトの可能なファイナライズ メソッドにも依存する可能性があります。

ConnectionManagerがシャットダウン時に保留中のすべてのリソースを実際に正常に閉じると仮定してみましょう。それでもエンティティを消費する必要がありますか? はいと言います。なぜなら、今から 1 か月後に誰かがあなたのコードを変更し、同じ try/finally ブロックで 2 回目の HTTP 呼び出しを行う可能性があります。クライアントが単一の接続プール上にある場合、最初の接続を解放しないと 2 番目の呼び出しが失敗します)。

つまり、私のポイントは次のとおりです。エンティティはリソースであり、リソースは不要になったときに解放する必要があります。後で他の人に解放してもらうことを当てにすることは、将来あなたを傷つける可能性があります. 原作者はそういう考えを持っていたのかもしれません。

補足として、あなたが書いた実装は実際には基礎となるストリームの最後までリーダーを消費することに注意してください。したがって、消費呼び出しは実際には何もしませんが、私の意見では、これは実装の詳細です (頭の中で、応答ストリームが完全に読み取られると、接続オブジェクトは自動的に解放され、http クライアントのプールに送り返されます)。また、API が提供する ResponseHandler メカニズムを使用する場合、この消費ロジックはすべて抽象化されていることにも注意してください。response.getEntity最後に、API はが決して null を返さないことを保証していないため、 NullPointerException.

于 2013-04-12T12:05:33.313 に答える