参考:https://blog.csdn.net/weixin_38106322/article/details/107549552
https://www.liaoxuefeng.com/wiki/1252599548343744/1306581226487842
parallel并行
list.stream().parallel().forEach(System.out::println);
// 查看到对应的接口
S parallel();
// 查看对应的管道实现,sourceStage.parallel = true;对流进行标记
@Override
@SuppressWarnings("unchecked")
public final S parallel() {
sourceStage.parallel = true;
return (S) this;
}
// 查看for的实现,这里进行了判断是否并行
@Override
public void forEach(Consumer<? super E_OUT> action) {
if (!isParallel()) {
sourceStageSpliterator().forEachRemaining(action);
}
else {
super.forEach(action);
}
}
// true执行evaluate
@Override
public void forEach(Consumer<? super P_OUT> action) {
evaluate(ForEachOps.makeRef(action, false));
}
// 三目运算符
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()));
}
// 注意看,这里是关键,这是一个default方法,所以如果继续看evaluateSequential就失去意义了,因为当前是一个接口,这个接口可能是被实现了。
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);
}
// 下面的是具体的实现,ordered是当并行需要顺序执行的时候,ForEachTask的invoke方法
@Override
public <S> Void evaluateParallel(PipelineHelper<T> helper,
Spliterator<S> spliterator) {
if (ordered)
new ForEachOrderedTask<>(helper, spliterator, this).invoke();
else
new ForEachTask<>(helper, spliterator, helper.wrapSink(this)).invoke();
return null;
}
// 再看ForEachTask类,继承CountedCompleter,继承ForkJoinTask,最后可以看到这个ForkJoinTask其实是Future的封装。invoke方法就来自ForkJoinTask,该方法是final修饰的,子类无法重写,所以这里实际实现了ForkJoinTask的方法,ForEachTask做了参数的设置。
static final class ForEachTask<S, T> extends CountedCompleter<Void> {
public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
// invoke
public final V invoke() {
int s;
if ((s = doInvoke() & DONE_MASK) != NORMAL)
reportException(s);
return getRawResult();
}
从stream看设计模式
ForkJoinTask
参考:https://blog.csdn.net/tyrroo/article/details/81390202
看下面submit的lambda表达式,无法区分多线程执行的是哪种任务,ForkJoinTask的特点并无法用lambda表达出来,并行可以实现计算的同步,下面例子中的递归就是并行运行。
- 关键分析
fork和join操作取代了多线程中的等待
MyForkJoinTask subTask1 = new MyForkJoinTask(startValue, (startValue + endValue) / 2);
subTask1.fork();
MyForkJoinTask subTask2 = new MyForkJoinTask((startValue + endValue) / 2 + 1 , endValue);
subTask2.fork();
return subTask1.join() + subTask2.join();
- 代码
public static void main(String[] args) throws ExecutionException, InterruptedException {
ForkJoinPool pool = new ForkJoinPool();
Integer MAX = 200;
Integer startValue = 1;
Integer endValue = 1001;
ForkJoinTask<Integer> submit = pool.submit(()->{
if (endValue-startValue<MAX) {
System.out.println("开始计算的部分:startValue = " + startValue + ";endValue = " + endValue);
Integer totalValue = 0;
for(int index = startValue ; index <= endValue ; index++) {
totalValue += index;
}
return totalValue;
} else {
MyForkJoin subTask1 = new MyForkJoin(startValue, (startValue + endValue) / 2);
subTask1.fork();
MyForkJoin subTask2 = new MyForkJoin((startValue + endValue) / 2 + 1 , endValue);
subTask2.fork();
return subTask1.join() + subTask2.join();
}
});
Integer integer = submit.get();
System.out.println(integer);
ForkJoinTask<Integer> submit1 = pool.submit(new MyForkJoin(1, 1001));
Integer integer1 = submit1.get();
System.out.println(integer1);
}
public class MyForkJoin extends RecursiveTask<Integer> {
private Integer MAX = 200;
private Integer startValue;
private Integer endValue;
public MyForkJoin(Integer startValue , Integer endValue) {
this.startValue = startValue;
this.endValue = endValue;
}
@Override
protected Integer compute() {
// 如果条件成立,说明这个任务所需要计算的数值分为足够小了
// 可以正式进行累加计算了
if(endValue - startValue < MAX) {
System.out.println("开始计算的部分:startValue = " + startValue + ";endValue = " + endValue);
Integer totalValue = 0;
for(int index = this.startValue ; index <= this.endValue ; index++) {
totalValue += index;
}
return totalValue;
}
// 否则再进行任务拆分,拆分成两个任务
else {
MyForkJoin subTask1 = new MyForkJoin(startValue, (startValue + endValue) / 2);
subTask1.fork();
MyForkJoin subTask2 = new MyForkJoin((startValue + endValue) / 2 + 1 , endValue);
subTask2.fork();
return subTask1.join() + subTask2.join();
}
}
}