除了Parallel流之外,Java如何实现隐式并发

时间:2016-01-19 13:05:36

标签: java concurrency parallel-processing

您好我是一名初学程序员,正在研究隐式和显式并发的不同变体,我看到自从引入了Java 8并行流,它允许并行并发,但我实际上并不了解编译器如何处理这个问题!流是否被分解为单个线程并同时运行?此外,如果这会导致任何错误或问题,例如使用显式并发时可以看到的内容。

2 个答案:

答案 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)