Haruskah instance Java 8 Stream selalu dekat () 'd?

12

Quoth the Javadoc :

Streaming memiliki metode BaseStream.close () dan mengimplementasikan AutoCloseable, tetapi hampir semua contoh aliran tidak perlu ditutup setelah digunakan. Secara umum, hanya stream yang sumbernya adalah saluran IO (seperti yang dikembalikan oleh Files.lines (Path, Charset)) akan memerlukan penutupan. Sebagian besar stream didukung oleh koleksi, array, atau fungsi pembangkit, yang tidak memerlukan manajemen sumber daya khusus. (Jika streaming memang membutuhkan penutupan, itu dapat dinyatakan sebagai sumber daya dalam pernyataan coba-dengan-sumber daya).

"Hampir semua" dan "umumnya" tidak jelas - jika Anda menulis perpustakaan dan mengabstraksi sumber Stream Anda dari pengguna Stream itu, maka Anda selalu harus bertanya pada diri sendiri pertanyaan - "haruskah saya menutup ini?" Streaming yang didukung IO perlu ditutup karena operasi terminal tidak menelepon close, jadi secara efektif saya selalu harus mengingat / mendokumentasikan dari mana aliran saya berasal, atau saya harus selalu melakukannya close.

Pilihan nuklir yang saya kira adalah tidak mengembalikan Streaming dari metode atau menerima parameter Stream, yang merupakan sentimen yang telah digaungkan oleh beberapa orang di tim JDK. Saya menemukan bahwa terlalu membatasi mempertimbangkan manfaat praktis dari Streaming.

Apa praktik terbaik Anda saat menutup Streaming? Saya mencari online untuk jawaban ini dari beberapa orang JDK yang biasanya aktif pada pertanyaan komunitas yang serupa, tetapi tidak menemukan sesuatu yang relevan.

RuslanD
sumber
Bukan pengembang Java, tapi saya akan menggunakan aturan ini: - Jika aliran dilewatkan sebagai argumen, mendokumentasikan bahwa pemanggil harus menutup aliran jika diperlukan; - Jika aliran dikembalikan kepada Anda dari suatu fungsi, anggap Anda harus menutupnya.
Bart van Ingen Schenau

Jawaban:

6

Seperti yang Anda katakan, di Jawa Anda harus tahu persis siapa yang bertanggung jawab untuk membebaskan sumber daya mana, sehingga Anda dapat memasukkan konstruk coba tangkapan yang sesuai, sumber daya coba atau entah bagaimana mendelegasikan tugas itu.

Satu-satunya hal yang dapat Anda andalkan pada GC untuk dibersihkan adalah 100% memori murni.
Jika mungkin ada beberapa sumber daya lain yang tercampur, satu-satunya hal yang dapat Anda lakukan secara wajar hanyalah memainkannya dengan aman.

Deduplicator
sumber
Jadi pada dasarnya closeadalah satu-satunya alternatif yang aman? Saya kira pertanyaannya adalah bagaimana tidak membuat kode terlihat terlalu jelek setiap kali Stream akan berguna untuk digunakan.
RuslanD
1
Ya, jika ada mungkin menjadi sumber non-memori, hal hanya aman untuk dilakukan adalah menganggap ada yang . Tidak ada jalan lain, meskipun Jawa sangat tidak cocok untuk sumber daya non-GC'd.
Deduplicator
Jadi jika itu hanya aliran antara dua koleksi (memori murni), menutupnya tidak perlu?
Amalgovinus
@Amalgovinus benar
Brad Cupit
5

Sejauh "praktik terbaik" berjalan, saya pikir itu ide yang baik untuk menggunakan konvensi penamaan untuk metode yang mengembalikan "aliran sumber daya".

Jika aliran harus close()diedit, hubungi metode pabrik open()atau openStream(). Sebut metode yang membangun aliran sesaat stream(), mengikuti konvensi yang ditetapkan oleh SDK. Selalu beri javadoc pada metode untuk memberi tahu klien bahwa mereka harus close()melakukannya.

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

Saya berharap penulis SDK tidak memilih untuk memakai AutoCloseablekelas aliran dasar. ResourceStreamSubtipe yang berbeda , yang mengimplementasikan secara sepele AutoCloseable, akan membuat kontrak yang berbeda jelas. Maka Anda tidak dapat menutup Streamyang tidak membutuhkannya, dan Anda dapat mendeteksi potensi kesalahan ResourceStreamdalam alat analisis statis.

Bergantung pada kebutuhan basis kode Anda (dan kemampuan Anda untuk menegakkan konvensi dalam tinjauan kode), Anda dapat membuat sendiri stream subclass yang disyaratkan sendiri. Atau jika Anda ingin membangun alat analisis statis Anda sendiri, metode anotasi yang menandai sumber daya yang dikelola secara langsung.

@RequiresClose
Stream<RECORD> openStream(URI source) throws IOException { ... }
Jason Trump
sumber