2013-04-12 24 views
26

Tôi đã xem qua EntityUtils.consume(httpEntity); và tôi không chắc nó thực sự làm gì.Tại sao tác giả sử dụng EntityUtils.consume (httpEntity) ;?

Ví dụ:

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

Tại sao tác giả đưa vào EntityUtils.consume(httpEntity); khi khối finally sẽ đóng kết nối và thu gom rác sẽ chăm sóc httpEntity?

Trả lời

31

Nó thực sự thích hợp để trở thành một "công dân tốt" (và thực sự biết các hợp đồng của HTTPClient giao diện). Điều gì EntityUtils.consume sẽ làm là giải phóng tất cả các tài nguyên được giữ bởi httpEntity, về cơ bản ngụ ý phát hành bất kỳ luồng cơ bản nào và cho đối tượng Connection quay lại hồ bơi của nó (trong trường hợp trình quản lý kết nối của bạn là đa luồng) hoặc giải phóng trình quản lý kết nối. có thể xử lý yêu cầu tiếp theo.

Nếu bạn không tiêu thụ entity, điều gì xảy ra thực sự phụ thuộc vào những gì "tắt trình quản lý kết nối" có nghĩa là trong điều khoản cuối cùng. Nó sẽ đóng các luồng/kết nối đang chờ xử lý chưa được gửi trở lại hồ bơi? Tôi không chắc chắn nó sẽ hợp đồng làm điều đó (mặc dù thực hiện khôn ngoan tôi nghĩ rằng nó không). Nếu không, bạn có thể bị rò rỉ tài nguyên hệ thống (ổ cắm vv). Điều gì xảy ra cũng có thể phụ thuộc vào một phương thức hoàn thiện có thể có của đối tượng Entity (nếu nó được thực thi) giải phóng tài nguyên của nó, một lần nữa, không chắc chắn nó nằm trong hợp đồng của thực thể để thực hiện điều đó.

Giả sử trong một phút rằng ConnectionManager thực sự đóng tất cả các tài nguyên đang chờ xử lý một cách duyên dáng khi nó tắt. Bạn vẫn cần phải tiêu thụ thực thể? Tôi nói có, bởi vì một tháng kể từ bây giờ, ai đó sẽ sửa đổi mã của bạn và thực hiện cuộc gọi HTTP thứ hai trong cùng một khối try/finally và có thể không làm như vậy vì bạn không giải phóng tài nguyên theo cách bạn cần (ví dụ: bạn là khách hàng trên một hồ bơi kết nối duy nhất, không giải phóng kết nối đầu tiên sẽ làm cho một cuộc gọi thứ hai thất bại).

Vì vậy, quan điểm của tôi là: Thực thể là tài nguyên và tài nguyên cần được giải phóng khi không cần thiết. Đếm những người khác để giải phóng họ cho bạn sau này có thể làm bạn tổn thương trong tương lai. Tác giả ban đầu có thể đã nghĩ theo những dòng đó. Lưu ý rằng việc thực hiện bạn đã viết sẽ thực sự tiêu thụ người đọc đến cuối dòng cơ bản, do đó, cuộc gọi tiêu thụ thực sự sẽ không làm gì cả, nhưng theo ý kiến ​​của tôi, đây là chi tiết triển khai (ngoài đỉnh đầu của tôi, một khi dòng phản hồi đã được đọc hoàn toàn, đối tượng kết nối sẽ tự động được phát hành/gửi trở lại hồ bơi trong máy khách http). Cũng lưu ý rằng tất cả logic Consume này cũng được trừu tượng hóa khỏi bạn nếu bạn sử dụng tính năng phân phối ResponseHandler mà API cung cấp. Cuối cùng, API không đảm bảo rằng response.getEntity sẽ không bao giờ trả về giá trị rỗng, vì vậy bạn nên kiểm tra để tránh NullPointerException.