简体   繁体   中英

Does Stream.parallel() use a new thread?

So, I'm trying to get my head around the Stream API introduced in Java 8. I'm trying to make a stream that can run on a separate thread (just for educational purposes)

String oracle = "http://www.oracle.com";
URL url = new URL(oracle);
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
in.lines().parallel().forEach(System.out::println);
System.out.print("CLOSING THE INPUT STREAM!, shouldnt this crash?");
in.close();

The outcome is not what I would expect.. (I was expecting a crash, since I closed the input stream while the other thread is reading from it). Note the .parallel() method call. Instead the code seems to be executing in a sequential manner with no problems.

OUTPUT:

<script language="JavaScript" src="http://www.oracleimg.com/us/assets/metrics/ora_ocom_hp.js"></script>
<!-- End SiteCatalyst code --> 

            <!-- SS_END_SNIPPET(fragment6,1)-->
<!-- SS_BEGIN_SNIPPET(fragment7,ui)-->          <!-- SS_END_SNIPPET(fragment7,ui)-->
</html>
CLOSING THE INPUT STREAM!, shouldnt this crash?

Does anyone know what's going on? Why is my code not crashing?

The parallel stream will indeed attempt splitting the work of reading the lines to mutiple threads. But the invocation itself is blocking, ie the statement waits until all threads finished to proceed to the next statement (where you close the input stream).

One thing to note is that forEach does not guarantee that the parallel actions execute in the same order of the stream elements, so the printed lines in this case may not be in the same order with the original Web page (see https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#forEach-java.util.function.Consumer- ).

If you want to execute things in the background without immediately blocking for their completion you can use java.util.concurrent.CompletableFuture.runAsync(Runnable) and related methods. It returns a CompletableFuture which can be joined later if needed.

As it was already noted, parallel stream blocks the current thread until all the parallel tasks are finished. In fact current thread is usually also used to perform some work, but if it finishes its part, then it waits for other threads (or steals some of their work to help them).

There's one special case though: if the parallel stream operation throws an Exception, then your stream processing in the main thread finishes (exceptionally), but other background threads may still continue processing some input chunks. You can check this using the following code:

// Create list of Strings "0", "1", "2", ..., "99"
List<String> list = IntStream.range(0, 100).mapToObj(String::valueOf)
                             .collect(Collectors.toCollection(ArrayList::new));
// replace one with non-numeric
list.set(1, "foo");

// Convert every string to number and print it
try {
    list.parallelStream().mapToInt(Integer::parseInt).forEach(System.out::println);
} catch (NumberFormatException e) {
    // well some non-number encountered
}
System.out.println("Exited");

Running this code you may occasionally see that some numbers are printed after the "Exited" message.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM