您好我是一名初学程序员,正在研究隐式和显式并发的不同变体,我看到自从引入了Java 8并行流,它允许并行并发,但我实际上并不了解编译器如何处理这个问题!流是否被分解为单个线程并同时运行?此外,如果这会导致任何错误或问题,例如使用显式并发时可以看到的内容。
答案 0 :(得分:1)
我看到自从引入Java 8并行流以来就允许了 对于并行并发,但我实际上并不了解如何 编译器处理这个!流被分解为单个线程 并同时运行?
我不是100%肯定,但AFAIK并行流使用Java SE 7中引入的fork/join framework。
通过研究这个框架,您可以更好地理解并行流如何在内部工作。
答案 1 :(得分:0)
我看到自从引入了Java 8并行流以实现并行并发,但我实际上并不了解编译器如何处理这个问题!
javac
编译不知道。 parallelStream()
是库中的一个方法,编译器不知道它的作用。
流是否分解为单个线程并同时运行?
Streams库尝试将工作分解为任务(每个CPU大约2个),并使用ForkJoinPool.commonPool()
此外,如果这会导致任何错误或问题,例如使用显式并发时可以看到的问题
如果抛出异常,则会捕获并重新抛出,就好像它已经在当前线程中抛出一样。
你可以尝试
IntStream.range(0, 16).parallel()
.forEach(i -> System.out.println(Thread.currentThread()));
IntStream.range(0, 16).parallel()
.forEach(i -> {
if (Thread.currentThread().getName().endsWith("-2"))
throw new RuntimeException();
Thread.yield();
});
打印
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[ForkJoinPool.commonPool-worker-11,5,main]
Thread[ForkJoinPool.commonPool-worker-13,5,main]
Thread[ForkJoinPool.commonPool-worker-9,5,main]
Thread[ForkJoinPool.commonPool-worker-13,5,main]
Thread[ForkJoinPool.commonPool-worker-9,5,main]
Thread[ForkJoinPool.commonPool-worker-13,5,main]
Thread[ForkJoinPool.commonPool-worker-8,5,main]
Thread[ForkJoinPool.commonPool-worker-9,5,main]
Thread[ForkJoinPool.commonPool-worker-2,5,main]
Thread[ForkJoinPool.commonPool-worker-4,5,main]
Thread[ForkJoinPool.commonPool-worker-4,5,main]
Thread[main,5,main]
Exception in thread "main" java.lang.RuntimeException: java.lang.RuntimeException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:593)
at java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:677)
at java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:735)
at java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:160)
at java.util.stream.ForEachOps$ForEachOp$OfInt.evaluateParallel(ForEachOps.java:189)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
at java.util.stream.IntPipeline.forEach(IntPipeline.java:404)
at java.util.stream.IntPipeline$Head.forEach(IntPipeline.java:560)
at B.main(B.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.lang.RuntimeException
at B.lambda$main$1(B.java:21)
at B$$Lambda$2/1452126962.accept(Unknown Source)
at java.util.stream.ForEachOps$ForEachOp$OfInt.accept(ForEachOps.java:205)
at java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:110)
at java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:693)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:512)
at java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:291)
at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1689)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)