Подтвердить что ты не робот

Почему автор использовал 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?

4b9b3361

Ответ 1

Это действительно сводится к тому, чтобы быть "хорошим гражданином" (и действительно зная контракты интерфейсов HTTPClient). То, что EntityUtils.consume будет делать, это освободить все ресурсы, хранящиеся в httpEntity, что по существу предполагает освобождение любого базового потока и возвращение объекта Connection в его пул (в случае, если ваш диспетчер подключений является многопоточным) или освобождение диспетчера подключений так что он может обработать следующий запрос.

Если вы не потребляете entity, то, что происходит, действительно зависит от того, что означает "выключение менеджера соединений" в предложении finally. Будет ли он закрывать ожидающие потоки/соединения, которые не были отправлены обратно в пул? Я не уверен, что это будет делать это по контракту (хотя, по-моему, это так и есть). Если это не так, вы можете протекать системные ресурсы (сокеты и т.д.). То, что происходит, также может зависеть от возможного метода финализации объекта Entity, который может (если он вообще выполняется) освободить его ресурсы, опять же, не уверен, что он заключен в контракте с сущностью.

Предположим, что в течение минуты, когда ConnectionManager изящно закрывает все ожидающие ресурсы, когда он выключается. Вам все еще нужно будет потреблять Сущность? Я говорю "да", потому что через один месяц кто-то изменит ваш код и сделает второй HTTP-вызов в том же блоке try/finally, и может быть неспособен сделать это, потому что вы не освободили ресурсы так, как вам нужно (например, если вы находитесь в одном пуле соединений, а не освобождая первое соединение, произойдет сбой второго вызова).

Итак, я хочу сказать: сущности - это ресурсы, а ресурсы должны быть освобождены, когда они не нужны. Рассчитывая на других, чтобы освободить их для вас в более поздний момент, может нанести вам вред в будущем. Возможно, оригинальный автор мог подумать об этом.

В качестве примечания обратите внимание, что написанная вами реализация на самом деле потребляет читателя до конца базового потока, поэтому вызов потребления фактически ничего не будет делать, но, на мой взгляд, это деталь реализации ( из-за верхней части головы, как только поток ответов был полностью прочитан, объект соединения автоматически освобождается/отправляется обратно в пул в http-клиенте). Обратите также внимание на то, что вся эта логика потребления также абстрагируется от вас, если вы используете предложенный API ResponseHandler. Наконец, API не гарантирует, что response.getEntity никогда не вернет значение null, поэтому вы должны проверить, чтобы избежать NullPointerException.