为什么说Java8的Stream并行流底层使用了Fork/Join框架

先写一个Java8Stream并行流的demo,如下:

import java.util.stream.Stream;

public class AtomicIntegerArrayTest {
    public static void main(String[] args) {
        Stream.of(1, 2, 3, 4, 5).parallel().reduce((a, b) -> {
            return a + b;
        }).ifPresent(System.out::println);
    }
}

以上的结果是1-5的累加值,如下:
在这里插入图片描述
先看看parallel()方法,进入相关的类AbstractPipeline中,如下:

abstract class AbstractPipeline<E_IN, E_OUT, S extends BaseStream<E_OUT, S>>
        extends PipelineHelper<E_OUT> implements BaseStream<E_OUT, S> {
private final AbstractPipeline sourceStage;

private boolean parallel;
@Override
@SuppressWarnings("unchecked")
public final S parallel() {
    sourceStage.parallel = true;
    return (S) this;
}
}

可以发现parallel()方法做的事很简单,就是标记个并行的标记,设置为true。

那么接下来看看reduce()方法:

abstract class ReferencePipeline<P_IN, P_OUT>
        extends AbstractPipeline<P_IN, P_OUT, Stream<P_OUT>>
        implements Stream<P_OUT>  {
    @Override
    public final Optional<P_OUT> reduce(BinaryOperator<P_OUT> accumulator) {
        return evaluate(ReduceOps.makeRef(accumulator));
    }
}

接着evaluate()方法跟下去,如下:

abstract class AbstractPipeline<E_IN, E_OUT, S extends BaseStream<E_OUT, S>>
        extends PipelineHelper<E_OUT> implements BaseStream<E_OUT, S> {
        
    final <R> R evaluate(TerminalOp<E_OUT, R> terminalOp) {
        assert getOutputShape() == terminalOp.inputShape();
        if (linkedOrConsumed)
            throw new IllegalStateException(MSG_STREAM_LINKED);
        linkedOrConsumed = true;

        return isParallel()
               ? terminalOp.evaluateParallel(this, sourceSpliterator(terminalOp.getOpFlags()))
               : terminalOp.evaluateSequential(this, sourceSpliterator(terminalOp.getOpFlags()));
    }

    @Override
    public final boolean isParallel() {
        return sourceStage.parallel;
    }
}

从以上的三元表达式中可以得出,调用isParallel()方法会得到之前通过parallel()方法设置的true值,然后就会执行terminalOp.evaluateParallel(this, sourceSpliterator(terminalOp.getOpFlags()))方法,所以接着跟进看看evaluateParallel()方法。

首先会进入TerminalOp接口类,如下:

interface TerminalOp<E_IN, R> {

      default <P_IN> R evaluateParallel(PipelineHelper<E_IN> helper,
                                      Spliterator<P_IN> spliterator) {
        if (Tripwire.ENABLED)
            Tripwire.trip(getClass(), "{0} triggering TerminalOp.evaluateParallel serial default");
        return evaluateSequential(helper, spliterator);
    }
}

会发现这是接口的默认方法,由于使用的是reduce方法,所以看看其相应的实现类对evaluateParallel()方法的实现,如下:

final class ReduceOps {
         @Override
         public <P_IN> R evaluateParallel(PipelineHelper<T> helper,
                                         Spliterator<P_IN> spliterator) {
            return new ReduceTask<>(this, helper, spliterator).invoke().get();
        }
}

这时候会发现,该方法中new了一个ReduceTask类,然后调用了它的invoke()方法,看看ReduceTask类相关信息,最后会发现它的继承链是这样的:

ReduceTask->AbstractTask->CountedCompleter->ForkJoinTask

可以发现最终跟到了ForkJoinTask类中,然后点击跟进invoke()方法,会发现调用的其实是ForkJoinTask()的invoke()方法,该方法是final修饰的,子类无法重写,如下:

   public final V invoke() {
        int s;
        if ((s = doInvoke() & DONE_MASK) != NORMAL)
            reportException(s);
        return getRawResult();
    }

总结

通过以上几步源码的跟踪,可以证明Java8的Stream并行流底层确实是使用了Fork/Join框架。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值