Чи повинні екземпляри Java 8 Stream завжди бути близькими () 'd?


12

Помістіть Javadoc :

Потоки мають метод BaseStream.close () та реалізують функцію автозахисту, але майже всі екземпляри потоку насправді не потрібно закривати після використання. Зазвичай закриття потребуватимуть лише потоки, джерелом яких є канал IO (наприклад, ті, які повертаються Files.lines (Path, Charset)). Більшість потоків підтримуються колекціями, масивами або генеруючими функціями, які не потребують спеціального управління ресурсами. (Якщо потік вимагає закриття, його можна оголосити як ресурс у операції "спробування ресурсів".)

"Майже всі" та "загалом" розпливчасті - якщо ви пишете бібліотеку і ви абстрагуєте джерело свого потоку від користувачів цього потоку, то вам завжди все-таки слід задати собі питання - "чи варто закривати це? " Підтримувані IO потоки потрібно закрити, оскільки операції терміналу не дзвонять close, тому ефективно мені завжди доводиться або пам'ятати / документувати, звідки надходить мій потік, або мені завжди до closeнього.

Ядерним варіантом, мабуть, було б не повертати потоки з методів або приймати параметри потоку, що є почуттям, яке відлучили деякі люди в команді JDK. Я вважаю це занадто обмежуючим, враховуючи практичну корисність потоків.

Які ваші найкращі практики щодо закриття потоків? Я шукав в Інтернеті відповідь на це у деяких людей JDK, які зазвичай активні на подібні питання спільноти, але не знайшли нічого актуального.


Це не розробник Java, але я би використовував ці правила: - Якщо потік передається як аргумент, документуйте, що абонент повинен закрити потік, якщо це потрібно; - Якщо потік повернеться вам із функцій, припустіть, що вам потрібно його закрити.
Барт ван Інген Шенау

Відповіді:


6

Як ви вже говорили, в Java потрібно точно знати, хто відповідає за звільнення ресурсу, тому ви можете помістити у відповідні конструкти-провідні, try-with-ресурси або якось делегувати це завдання.

Єдине, на що ти можеш залежати від GC, щоб очистити для тебе, це 100% чиста пам'ять.
Якщо можуть бути змішані інші ресурси, єдине, що ви можете розумно зробити - це просто захистити його.


Так в основному closeце єдина безпечна альтернатива? Я думаю, питання полягає в тому, як не змусити код виглядати надто некрасивим кожен раз, коли потоку було б зручно використовувати.
RuslanD

1
Так, якщо можуть бути ресурси, які не є пам'яттю, єдине безпечне, що потрібно зробити, це припустити, що вони є . Ні в якому разі не можна, навіть якщо Java дуже непридатна для ресурсів, що не належать до GC.
Дедуплікатор

Тож якщо це просто потік між двома колекціями (чиста пам'ять), закривати це не потрібно?
Амальговінус

@Amalgovinus правильний
Брэд Купіт

5

Що стосується "кращих практик", я вважаю, що корисно використовувати конвенцію про іменування методів, які повертають "потоки ресурсів".

Якщо потік має бути close()відредагований, зателефонуйте до заводського методу open()або openStream(). Викликайте методи, які будують ефемерні потоки stream(), дотримуючись конвенції, встановленої SDK. Завжди покладіть javadoc на метод, щоб попередити клієнта про те, що він повинен close()це зробити.

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

Я хотів би, щоб автори SDK не вибрали класти AutoCloseableбазовий клас потоку. Різний ResourceStreamпідтип, який тривіально реалізує AutoCloseable, зробив би очевидними різні контракти. Тоді ви не змогли закрити Streamпотрібний йому елемент, і ви могли виявити потенційно неправильне керування ResourceStreamв інструментах статичного аналізу.

Залежно від потреб вашої кодової бази (і вашої здатності застосовувати конвенції в огляді коду), ви можете самостійно створити потрібний підклас потоку. Або якщо ви хочете створити власні інструменти статичного аналізу, анотацію методу, яка безпосередньо позначає керовані ресурси.

@RequiresClose
Stream<RECORD> openStream(URI source) throws IOException { ... }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.