I'm creating multiple streams which I have to access in parallel (or possibly-parallel). I know how to make a try-with-resources when the amount of resources is fixed at compile-time, but what if the amount of resources is determined by a parameter?
I have something like this:
private static void foo(String path, String... files) throws IOException {
@SuppressWarnings("unchecked")
Stream<String>[] streams = new Stream[files.length];
try {
for (int i = 0; i < files.length; i++) {
final String file = files[i];
streams[i] = Files.lines(Paths.get(path, file))
.onClose(() -> System.out.println("Closed " + file));
}
// do something with streams
Stream.of(streams)
.parallel()
.flatMap(x -> x)
.distinct()
.sorted()
.limit(10)
.forEach(System.out::println);
}
finally {
for (Stream<String> s : streams) {
if (s != null) {
s.close();
}
}
}
}
close() method is used to close the writer. close() flushes and then closes the stream.
The java. io. InputStream. close() method closes this stream and releases any system resources associated with the stream.
yes you need to close stream because, the stream is already full with content and when you close the stream then you can use it again. also data is flush in drive when use flush method. when you close the stream JVM will see that stream is not can be use for further operation.
Therefore, if we forget to close the stream, the underlying channel will remain open and then we would end up with a resource leak.
You could write a composite AutoCloseable
for managing a dynamic amount of AutoCloseable
:
import java.util.ArrayList;
import java.util.List;
public class CompositeAutoclosable<T extends AutoCloseable> implements AutoCloseable {
private final List<T> components= new ArrayList<>();
public void addComponent(T component) { components.add(component); }
public List<T> getComponents() { return components; }
@Override
public void close() throws Exception {
Exception e = null;
for (T component : components) {
try { component.close(); }
catch (Exception closeException) {
if (e == null) { e = closeException; }
else { e.addSuppressed(closeException); }
}
}
if (e != null) { throw e; }
}
}
and you could use it in your method:
private static void foo(String path, String... files) throws Exception {
try (CompositeAutoclosable<Stream<String>> streams
= new CompositeAutoclosable<Stream<String>>()) {
for (int i = 0; i < files.length; i++) {
final String file = files[i];
streams.addComponent(Files.lines(Paths.get(path, file))
.onClose(() -> System.out.println("Closed " + file)));
}
streams.getComponents().stream()
.parallel()
.flatMap(x -> x)
.distinct()
.sorted()
.limit(10)
.forEach(System.out::println);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With