Le istanze di Java 8 Stream dovrebbero essere sempre chiuse () 'd?


12

Quoth the Javadoc :

Gli stream hanno un metodo BaseStream.close () e implementano AutoCloseable, ma quasi tutte le istanze di stream non devono essere chiuse dopo l'uso. In genere, solo gli stream la cui sorgente è un canale IO (come quelli restituiti da Files.lines (Path, Charset)) richiedono la chiusura. La maggior parte dei flussi è supportata da raccolte, matrici o funzioni di generazione, che non richiedono una gestione delle risorse speciale. (Se un flusso richiede la chiusura, può essere dichiarato come risorsa in un'istruzione try-with-resources.)

"Quasi tutti" e "generalmente" sono vaghi - se stai scrivendo una libreria e stai astraggendo la fonte del tuo Stream dagli utenti di quel Stream, allora devi sempre porti la domanda - "dovrei chiudere Questo?" I flussi supportati da IO devono essere chiusi perché le operazioni del terminale non chiamano close, quindi in modo efficace devo sempre ricordare / documentare da dove proviene il mio Stream o devo sempre closefarlo.

L'opzione nucleare credo sia quella di non restituire gli stream dai metodi o di accettare i parametri Stream, che è un sentimento che è stato fatto eco da alcune persone del team JDK. Trovo che sia eccessivamente limitante considerando l'utilità pratica degli stream.

Quali sono le tue migliori pratiche in merito alla chiusura di stream? Ho cercato online una risposta a questa domanda da parte di alcune persone del JDK che di solito sono attive su simili domande della comunità, ma non hanno trovato nulla di rilevante.


Non uno sviluppatore Java, ma vorrei utilizzare queste regole: - Se un flusso viene passato come argomento, documentare che il chiamante deve chiudere il flusso se necessario; - Se il flusso ti viene restituito da una funzione, supponi di doverlo chiudere.
Bart van Ingen Schenau,

Risposte:


6

Come hai detto, in Java devi sapere esattamente chi è responsabile della liberazione di quale risorsa, in modo da poter inserire gli appropriati costrutti try-catch, try-with-resources o in qualche modo delegare tale attività.

L'unica cosa che puoi fare affidamento sul GC per ripulirti è pura memoria al 100%.
Se potrebbero esserci altre risorse mescolate, l'unica cosa che puoi ragionevolmente fare è semplicemente giocare in sicurezza.


Quindi in pratica closeè l'unica alternativa sicura? Immagino che la domanda sia come non rendere il codice troppo brutto ogni volta che uno Stream sarebbe utile da usare.
RuslanD,

1
Sì, se potrebbero esserci risorse non di memoria, l'unica cosa sicura da fare è supporre che ci siano . Non c'è modo di aggirarlo, anche se Java è molto inadatto per risorse non GC.
Deduplicatore,

Quindi se è solo un flusso tra due raccolte (pura memoria), non è necessario chiuderlo?
Amalgovinus,

@Amalgovinus correct
Brad Cupit,

5

Per quanto riguarda le "migliori pratiche", penso che sia una buona idea utilizzare una convenzione di denominazione per i metodi che restituiscono "flussi di risorse".

Se è necessario modificare un flusso close(), chiamare il metodo factory open()o openStream(). Chiama metodi che costruiscono flussi effimeri stream(), seguendo la convenzione stabilita dall'SDK. Metti sempre javadoc sul metodo per avvisare il client che devono close()farlo.

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

Vorrei che gli autori dell'SDK non avessero scelto di inserire AutoCloseablela classe stream di base. Un ResourceStreamsottotipo distinto , che implementa banalmente AutoCloseable, avrebbe reso ovvi i diversi contratti. Quindi non è possibile chiudere uno Streamche non ne ha bisogno e si possono rilevare potenzialmente mal gestiti ResourceStreamnegli strumenti di analisi statica.

A seconda delle esigenze del tuo codebase (e della tua capacità di applicare convenzioni nella revisione del codice), potresti stabilire tu stesso una sottoclasse di stream strettamente richiesta. Oppure, se si desidera creare i propri strumenti di analisi statica, un'annotazione del metodo che contrassegna direttamente le risorse gestite.

@RequiresClose
Stream<RECORD> openStream(URI source) throws IOException { ... }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.