Закрытие потоков в середине трубопроводов
Когда я выполняю этот код, который открывает много файлов во время потокового конвейера:
public static void main(String[] args) throws IOException {
Files.find(Paths.get("JAVA_DOCS_DIR/docs/api/"),
100, (path, attr) -> path.toString().endsWith(".html"))
.map(file -> runtimizeException(() -> Files.lines(file, StandardCharsets.ISO_8859_1)))
.map(Stream::count)
.forEachOrdered(System.out::println);
}
Я получаю исключение:
java.nio.file.FileSystemException: /long/file/name: Too many open files
Проблема в том, чтоStream.count
не закрывает поток после его прохождения. Но я не понимаю, почему это не следует делать, учитывая, что это терминальная операция. То же самое верно для других операций терминала, таких какreduce
а такжеforEach
. flatMap
с другой стороны, закрывает потоки, из которых он состоит.
Документация говорит мне использовать оператор try-with-resouces-для закрытия потоков, если это необходимо. В моем случае я мог бы заменитьcount
строка с чем-то вроде этого:
.map(s -> { long c = s.count(); s.close(); return c; } )
Но это шумно и некрасиво и может стать настоящим неудобством в некоторых случаях с большими и сложными трубопроводами.
Итак, мои вопросы следующие:
Почему потоки не были спроектированы так, чтобы терминальные операции закрывали потоки, над которыми они работают? Это позволило бы им лучше работать с потоками ввода-вывода.Каково лучшее решение для закрытия потоков ввода-вывода в конвейерах?runtimizeException
это метод, который оборачивает проверенное исключение вRuntimeException
s.