简体   繁体   English

Stream.parallel()是否使用新线程?

[英]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) 所以,我试图了解Java 8中引入的Stream API。我正在尝试创建一个可以在单独的线程上运行的流(仅用于教育目的)

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. 注意.parallel()方法调用。 Instead the code seems to be executing in a sequential manner with no problems. 相反,代码似乎以顺序方式执行而没有任何问题。

OUTPUT: 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- ). 需要注意的一点是, forEach并不保证并行操作的执行顺序与流元素的顺序相同,因此在这种情况下,打印的行与原始Web页面的顺序可能不同(请参阅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. 如果要在后台执行操作而不立即阻止它们的完成,可以使用java.util.concurrent.CompletableFuture.runAsync(Runnable)和相关方法。 It returns a CompletableFuture which can be joined later if needed. 它返回一个CompletableFuture,如果需要可以在以后加入。

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. 运行此代码时,您可能偶尔会看到在"Exited"消息后打印一些数字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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