Các cá thể Luồng Java 8 phải luôn luôn đóng () 'd?


12

Làm tiêu tan Javadoc :

Các luồng có phương thức BaseStream.close () và triển khai AutoClosizable, nhưng gần như tất cả các trường hợp luồng không thực sự cần phải đóng sau khi sử dụng. Nói chung, chỉ các luồng có nguồn là kênh IO (chẳng hạn như các luồng được trả về bởi Files.lines (Đường dẫn, Bộ ký tự)) sẽ yêu cầu đóng. Hầu hết các luồng được hỗ trợ bởi các bộ sưu tập, mảng hoặc các hàm tạo, không yêu cầu quản lý tài nguyên đặc biệt. (Nếu một luồng yêu cầu đóng, nó có thể được khai báo dưới dạng tài nguyên trong câu lệnh try-with-resource.)

"Gần như tất cả" và "nói chung" là mơ hồ - nếu bạn đang viết thư viện và bạn đang trừu tượng hóa nguồn Luồng của mình từ những người dùng Luồng đó, thì bạn luôn phải tự hỏi mình câu hỏi - "tôi có nên đóng không điều này?" Các luồng được hỗ trợ bởi IO cần phải được đóng lại vì các hoạt động của thiết bị đầu cuối không gọi close, vì vậy, tôi luôn phải nhớ / ghi lại nơi luồng của tôi đến hoặc tôi luôn phải thực hiện close.

Tùy chọn hạt nhân mà tôi đoán sẽ không trả về Luồng từ các phương thức hoặc chấp nhận tham số Luồng, đây là một tình cảm đã được một số người trong nhóm JDK lặp lại. Tôi thấy rằng việc giới hạn quá mức khi xem xét tính hữu dụng thực tế của Luồng.

Thực tiễn tốt nhất của bạn xung quanh việc đóng Luồng là gì? Tôi đã tìm kiếm câu trả lời trực tuyến cho một số người trong nhóm JDK, những người thường hoạt động trong các câu hỏi tương tự của cộng đồng, nhưng không tìm thấy bất cứ điều gì có liên quan.


Không phải là nhà phát triển Java, nhưng tôi sẽ sử dụng các quy tắc sau: - Nếu một luồng được truyền dưới dạng đối số, tài liệu mà người gọi phải đóng luồng nếu cần; - Nếu luồng được trả về cho bạn từ một hàm, giả sử bạn cần đóng nó.
Bart van Ingen Schenau

Câu trả lời:


6

Như bạn đã nói, trong Java, bạn cần biết chính xác ai chịu trách nhiệm giải phóng tài nguyên nào, vì vậy bạn có thể đưa vào các cấu trúc try-Catch-Catch, try-with-resource hoặc bằng cách nào đó ủy thác nhiệm vụ đó.

Điều duy nhất mà bạn có thể phụ thuộc vào GC để dọn dẹp cho bạn là bộ nhớ thuần 100%.
Nếu có thể có một số tài nguyên khác được trộn lẫn, điều duy nhất bạn có thể làm một cách hợp lý chỉ đơn giản là chơi nó an toàn.


Vì vậy, về cơ bản closelà sự thay thế an toàn duy nhất? Tôi đoán câu hỏi là làm thế nào để không làm cho mã trông quá xấu xí mỗi khi Stream sẽ tiện sử dụng.
RuslanD

1
Vâng, nếu có thể được tài nguyên không nhớ, điều duy nhất an toàn để làm là giả sử có được . Không có cách nào khác, mặc dù Java rất không phù hợp với các tài nguyên không phải là GC.
Ded repeatator

Vì vậy, nếu nó chỉ là một luồng giữa hai bộ sưu tập (bộ nhớ thuần), việc đóng nó không cần thiết?
Amalgovinus

@Amalgovinus đúng
Brad Cupit

5

Theo như "cách thực hành tốt nhất", tôi nghĩ nên sử dụng quy ước đặt tên cho các phương thức trả về "luồng tài nguyên".

Nếu một luồng phải được close()ed, hãy gọi phương thức nhà máy open()hoặc openStream(). Gọi các phương thức xây dựng các luồng phù du stream(), theo quy ước được thiết lập bởi SDK. Luôn đặt javadoc trên phương thức để thông báo cho khách hàng rằng họ phải làm close()điều đó.

public interface StreamingServer<RECORD> {
    /** 
     * Return a memory-efficient record stream from {@code source}.
     * Clients <em>must</em> call {@link Stream#close} to dispose the
     * stream.
     */
    Stream<RECORD> openStream(URI source) throws IOException;
}

Tôi ước các tác giả SDK đã không chọn đưa AutoCloseablevào lớp luồng cơ sở. Một ResourceStreamkiểu con riêng biệt , mà thực hiện tầm thường AutoCloseable, sẽ làm cho các hợp đồng khác nhau rõ ràng. Sau đó, bạn không thể đóng một Streamcái không cần nó và bạn có thể phát hiện ra khả năng bị quản lý sai ResourceStreamtrong các công cụ phân tích tĩnh.

Tùy thuộc vào nhu cầu của cơ sở mã của bạn (và khả năng của bạn để thực thi các quy ước trong đánh giá mã), bạn có thể tự mình thiết lập một lớp con luồng yêu cầu chặt chẽ. Hoặc nếu bạn muốn xây dựng các công cụ phân tích tĩnh của riêng mình, một chú thích phương thức đánh dấu trực tiếp các tài nguyên được quản lý.

@RequiresClose
Stream<RECORD> openStream(URI source) throws IOException { ... }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.