源码:跟踪Stream并行流工作原理
List<String> lst0 = Arrays.asList("a0are", "a1where", "a2anvato", "a3java", "b4abc", "b5123", "c6hello", "c7world", "d8!!!");
ArrayList<String> list = new ArrayList<>(lst0);
List<String> result =
list.parallelStream() //定义输入源, 得到Stage0 Head节点(流)
.filter(s -> s.startsWith("a")) //定义中间操作, 得到Stage1 StatelessOp节点(流)
.sorted() //定义中间操作, 得到Stage2 StatefulOp节点(流),SortedOps.OfRef实例
.limit(3) //定义中间操作, 得到Stage3 StatefulOp节点(流),SliceOps的StatefulOp实例
.map(s -> s.subString(1)) //定义中间操作, 得到Stage4 StatelessOp节点(流)
.collect(Collectors.toList()); //定义终端操作, TerminalOp节点(流),ReduceOp实例
list.parallelStream()语句:分析
list当前是ArrayList类的一个实例,查看ArrayList类源码后,发现ArrayList类内没有parallelStream()方法;继续查看List接口,发现List接口也没有parallelStream()方法;继续查看超级Collection接口,发现内部有默认的parallelStream()方法,这是jdk1.8版本新引入的一种技术手段,接口内可以拥有默认的实现方法。
JDK8新增:接口中可提供默认方法 default修饰符。默认实现可以从本质上根除适配器模式。
JDK8新增:接口中可提供静态方法 static修饰符。可以 接口名.静态方法() 来调用。
JDK8新增:接口中可声明变量,隐式默认为public final static
- Collection接口的parallelStream()方法
//Collection集合超级接口内的默认方法
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true); //并行流
}
spliterator()方法,当前调用parallelStream()的对象list是ArrayList类的实例,所以先看看ArrayList类中有没有spliterator方法,查看源码后,发现ArrayList类中有spliterator方法
- ArrayList类的spliterator()方法
public Spliterator<E> spliterator() {
return new ArrayListSpliterator<>(this, 0, -1, 0);
//返回一个拆分迭代器,初始时为index=0起使,fence=-1围栏,修改次数0
}
//ArrayList的内部类
static final class ArrayListSpliterator<E> implements Spliterator<E> {
private final ArrayList<E> list;
private int index; // current index, modified on advance/split
private int fence; // -1 until used; then one past last index
private int expectedModCount; // initialized when fence set
/** Create new spliterator covering the given range */
ArrayListSpliterator(ArrayList<E> list, int origin, int fence, int expectedModCount) {
this.list = list; // OK if null unless traversed
this.index = origin;
this.fence = fence;
this.expectedModCount = expectedModCount;
}
public int characteristics() {//特性值集:有序且知晓大小的
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
}
拿到了一个拆分器ArrayListSpliterator(list,0,-1,0)后,接着看语句StreamSupport.stream(spliterator(), true);
- StreamSupport.stream(spliterator,true)方法
public static <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel) {
return new ReferencePipeline.Head<>(
spliterator, //上方拿到的ArrayListSpliterator(list,0,-1,0);
StreamOpFlag.fromCharacteristics(spliterator),
parallel);
}
//StreamOpFlag类的静态方法
static int fromCharacteristics(Spliterator<?> spliterator) {
int characteristics = spliterator.characteristics();
if ((characteristics & Spliterator.SORTED) != 0 && spliterator.getComparator() != null) {
// Do not propagate the SORTED characteristic if it does not correspond
// to a natural sort order
return characteristics & SPLITERATOR_CHARACTERISTICS_MASK & ~Spliterator.SORTED;
}
else {
return characteristics & SPLITERATOR_CHARACTERISTICS_MASK; //拆分器特性值的掩码
}
}
//ReferencePipeline类的内部类(ReferencePipeline实现了stream部分接口,继承AbstractPipeline类)
static class Head<E_IN, E_OUT> extends ReferencePipeline<E_IN, E_OUT> {
//Head节点的构造函数,Head是个流,代表Stage0
Head(Spliterator<?> source, int sourceFlags, boolean parallel) {
super(source, sourceFlags, parallel);
}
}
//Head节点最终调用的构造函数在AbstractPipeline中(Stage0~StageN的构造函数都在AbstractPipeline类中)
AbstractPipeline(Spliterator<?> source, int sourceFlags, boolean parallel) {
this.previousStage = null; //Head节点无前序节点
this.sourceSpliterator = source; //上方拿到的ArrayListSpliterator(list,0,-1,0);
this.sourceStage = this;
this.sourceOrOpFlags = sourceFlags & StreamOpFlag.STREAM_MASK;
this.combinedFlags = (~(sourceOrOpFlags << 1)) & StreamOpFlag.INITIAL_OPS_VALUE;
this.depth = 0; //Head节点深度0
this.parallel = parallel; //Head节点流是并行流
}
list.parallelStream()语句:结果:拿到Head节点并行流,Stage0节点建立完毕
现在我们拿到这句话的执行结果,得到了一个Head节点流,也即Stage0阶段,该Head节点流是个并行流,深度0。为了简化理解,我们现在不谈及掩码(也就是MASK或者说Flags)的问题,掩码的存在是为了提高优化并行的运算而设计的,并不会影响我们写的主体业务逻辑代码,优化机制是JVM内部做的,当然,我们很清楚掩码的作用,那么就能写出来更高质量的代码,关于掩码的讲解,在另外一节来专门讲解。现在,我们就假定没搞掩码,自然无法通知JVM做一些优化策略,就全当JVM累点,土了一点,别优化给我好好的执行代码就行。
Stage0.filter(s -> s.startsWith("a")) 语句:分析
//调用filter方法时,是Head节点也即Stage0阶段 调用的,所以filter的入参this是Head节点对象
public final Stream<P_OUT> filter(Predicate<? super P_OUT> predicate) {
return new StatelessOp<P_OUT, P_OUT>(this, StreamShape.REFERENCE, StreamOpFlag.NOT_SIZED) {
Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {
//这里的方法体内容我先注释,后面在看,因为现在创建Stage阶段,还用不到opWrapSink方法
}
};
}
//StatelessOp类的构造函数
StatelessOp(AbstractPipeline<?, E_IN, ?> upstream, StreamShape inputShape, int opFlags) {
super(upstream, opFlags){
upstream.linkedOrConsumed = true;
upstream.nextStage = this; //Stage0的下一阶段是Stage1 双向链表的建立
this.upstream = upstream; //Stage1的前一阶段是Stage0 双向链表的建立
this.depth = upstream.depth + 1; //Stage1的深度是1
this.sourceStage = upstream.sourceStage;
this.sourceOrOpFlags = opFlags & StreamOpFlag.OP_MASK;
this.combinedFlags = StreamOpFlag.combineOpFlags(opFlags, upstream.combinedFlags);
}
}
/**
* filter方法调用后,我们得到了Stage1阶段,并且建立好了双向链表
*/
Stage0.filter()语句:结果:我们拿到了中间操作filter的节点,也即Stage1阶段已经建立完毕,并建立好双向链表
Stage1.sorted()语句:分析
public final Stream<P_OUT> sorted() {
return SortedOps.makeRef(this); //这个this是当前的Stage1
}
//SortedOps类的静态方法makeRef
static <T> Stream<T> makeRef(AbstractPipeline<?, T, ?> upstream) {
return new OfRef<>(upstream);
}
//SortedOps的内部类OfRef
private static final class OfRef<T> extends ReferencePipeline.StatefulOp<T, T> {
OfRef(AbstractPipeline<?, T, ?> upstream) {
super(upstream, StreamShape.REFERENCE, StreamOpFlag.IS_ORDERED | StreamOpFlag.IS_SORTED);
this.isNaturalSort = true;
Comparator<? super T> comp = (Comparator<? super T>) Comparator.naturalOrder();
this.comparator = comp;
}
public Sink<T> opWrapSink(int flags, Sink<T> sink){
//这里先注释掉,创建Stage2