java Stream使用记录
java中Stream本质上是把计算封装成一个任务,放到ForkJoin的commonPool中执行.
那么就看一下stream是扩展ForkJoin的结构:
Object (java.lang)
ForkJoinTask (java.util.concurrent)
CountedCompleter (java.util.concurrent)
AbstractTask (java.util.stream)
ReduceTask in ReduceOps (java.util.stream)
CollectorTask in Nodes (java.util.stream)
OfRef in CollectorTask in Nodes (java.util.stream)
OfDouble in CollectorTask in Nodes (java.util.stream)
OfLong in CollectorTask in Nodes (java.util.stream)
OfInt in CollectorTask in Nodes (java.util.stream)
AbstractShortCircuitTask (java.util.stream)
MatchTask in MatchOps (java.util.stream)
SliceTask in SliceOps (java.util.stream)
FindTask in FindOps (java.util.stream)
如上所示,我们发现AbstractTask是第一个扩展自ForkJoin原有结构抽象类:
如下:
@Override
public void compute() {
Spliterator<P_IN> rs = spliterator, ls; // right, left spliterators
long sizeEstimate = rs.estimateSize();
long sizeThreshold = getTargetSize(sizeEstimate);
boolean forkRight = false;
@SuppressWarnings("unchecked") K task = (K) this;
while (sizeEstimate > sizeThreshold && (ls = rs.trySplit()) != null) {//任务可以再次分割,分为左右两个计算节点
K leftChild, rightChild, taskToFork;
task.leftChild = leftChild = task.makeChild(ls);
task.rightChild = rightChild = task.makeChild(rs);
task.setPendingCount(1);
if (forkRight) {
forkRight = false;
rs = ls;
task = leftChild;
taskToFork = rightChild;
}
else {
forkRight = true;
task = rightChild;
taskToFork = leftChild;
}
taskToFork.fork();//放到ForkJoin的commonPool的工作队列中执行
sizeEstimate = rs.estimateSize();
}
task.setLocalResult(task.doLeaf());
task.tryComplete();//合并操作
}
以ReduceTask举例:
public void onCompletion(CountedCompleter<?> caller) {//注意一点每个节点只会有一个线程在运行,不会并发
if (!isLeaf()) {
S leftResult = leftChild.getLocalResult();
leftResult.combine(rightChild.getLocalResult());
setLocalResult(leftResult);
}
// GC spliterator, left and right child
super.onCompletion(caller);
}
下面是一点使用parallelStream流的心得:
请看下面的例子:
ArrayList<Integer> objects = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
objects.add(i);
}
System.out.println(objects.size());
List<Integer> al = new LinkedList<>();
objects.parallelStream()
.forEach(f -> al.add(f));
System.out.println(al.size());
List<Integer> collect = objects.parallelStream()
.map(m -> m)
.collect(Collectors.toList());
System.out.println(collect.size());
结果如下:
100000
70996
100000
在parallelStream中建议大家尽量不要再流处理过程中更改流以外的变量,如果想要使用请使用支持并发的类型.
本文深入探讨了Java中Stream并行处理的内部机制,详细解析了Stream如何通过ForkJoinPool实现并行计算,以及AbstractTask在并行处理中的核心作用。并通过实例对比了普通流与并行流在处理大量数据时的效率差异,强调了在并行流处理中避免修改外部变量的重要性。
5884

被折叠的 条评论
为什么被折叠?



