java-并行-stream().parallel()-多线程并行任务ForkJoinTask-forkjoin取代多线程的等待

26 篇文章 0 订阅


参考: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();
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值