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中建议大家尽量不要再流处理过程中更改流以外的变量,如果想要使用请使用支持并发的类型.