Почему не запускается поток Java close() после операции терминала?

После чтения https://www.airpair.com/java/posts/spring-streams-memory-efficiency у меня возникает соблазн вывести результаты из базы данных, но, как я обсуждал с коллегой (cfr. comment, он добавил к этой статье), необходимо помнить, что использовать конструкцию try-with-resources, чтобы избежать утечек памяти.

Ответы

Ответ 1

Поскольку потоки, требующие явного выделения ресурсов, на самом деле довольно необычный случай. Таким образом, мы решили не налагать на все потоковое исполнение что-то, что только полезно для 0,01% использования.

Мы создали Stream Autocloseable, чтобы вы могли освобождать ресурсы из источника, если хотите, но это то, где мы остановились, и по уважительной причине.

Мало того, что это автоматически компенсирует большинство пользователей дополнительной работой, которой они не нужны, но это также нарушит общий принцип: тот, кто выделяет ресурс, несет ответственность за закрытие ресурса. Когда вы вызываете

BufferedReader reader = ...
reader.lines().op().op()...

вы открываете ресурс, а не библиотеку потоков, и вы должны закрыть его. Фактически, поскольку закрытие потока, вызванного вызовом метода доступа на каком-то ресурсодержащем объекте, иногда закрывает базовый объект, вы, вероятно, не хотите, чтобы поток закрывал BufferedReader для вас - вы можете захотеть, чтобы он оставался открытым после вызова.

Если вы хотите закрыть ресурс, это тоже легко:

try (BufferedReader reader = ...) {
    reader.lines().op()...
}

Вероятно, вы используете потоки определенным образом, поэтому, вероятно, кажется "очевидным", какие потоки должны делать, но есть больше вариантов использования, чем у вас. Поэтому, вместо того, чтобы прибегать к конкретным случаям использования, мы подошли к нему по общему принципу: если вы открыли поток и хотите его закрыть, закройте его самостоятельно, но если вы его не открыли, вам не нужно закрывать.

Ответ 2

Я думаю, что вы смешиваете java.io.InputStream с java.util.stream.Stream, которые представляют собой две очень разные концепции.

try-with-resources работает с объектами, реализующими интерфейс Autoclosable, например InputStream s. InputStream представляют собой абстрактный источник данных, относящихся к IO.

java.util.stream.Stream<T>, с другой стороны, реализует концепцию из функционального программирования, которая представляет собой своего рода динамический набор, который не обязательно статически построен, но скорее может быть сгенерирован и, следовательно, потенциально бесконечен.

Что Марко Топольник (автор статьи, с которой вы связались), в основном делает в статье, предлагает способ обернуть источник IO в java.util.stream.Stream. Это довольно умный подход, но java.util.stream.Stream не предназначены для этой цели.

Поскольку они вообще не предназначены для использования с IO, нет причин для их включения закрытия после операций терминала.


ИЗМЕНИТЬ

После того, как вы выяснили, что вы на самом деле не перепутали эти два (извините за это), благодаря этому ответу, я обнаружил, что ваш точный например, в документации AutoCloseable (выделено мной мной):

Возможно, и фактически обычное, для базового класса для реализации AutoCloseable, хотя не все его подклассы или экземпляры будут иметь свободные ресурсы. Для кода, который должен работать в полном общности или когда известно, что экземпляр AutoCloseable требует освобождения ресурсов, рекомендуется использовать try-with-resources конструкции. Однако при использовании таких средств, как Stream, поддержка как форм ввода-вывода, так и не-входов-выходов, использование ресурсов блоки вообще не нужны при использовании форм, не содержащих I/O.

Ответ 3

Почему библиотека Java 8 не заботится о том, чтобы закрывать потоки после каждой операции терминала (без необходимости обертывания потокового экземпляра в try-with-resources)?

Поскольку исключение может возникать во время или до операции терминала, и потому, что вы не хотите, чтобы операция терминала закрывала поток. Вы можете использовать try-with-resource, если хотите, чтобы поток был закрыт.

Если применимо, существуют ли какие-либо планы по добавлению этой функции в Java или было бы целесообразно запросить ее?

Это не имеет смысла, см. ответ выше.