7-并发编程-Future&ForkJoin框架原理分析

超线程:虚拟出多个核
在这里插入图片描述
并发与并行
并发可认为是一种程序的逻辑结构的设计模式

  • 可以用并发的设计方式去设计模型,然后运行在一个单核系统上
  • 可以将这种模型不加修改地运行在多核系统上,实现真正的并行

并行是程序执行的一种属性
对Java而言,对支持Concurrency(并发)/Parallelism(并行)的不断完善,明显地体现在优化并发与并行

•Java 1 支持threads, locks, condition queues
•Java 5 引入了 thread pools, blocking queues, concurrent collections
•Java 7 加入了fork-join库
•Java 8 加入了 parallel streams

分治法
把一个规模大的问题划分为规模较小的子问题,然后分而治之,最后合并子问题的解得到原问题的解。步骤:

  • 分割原问题:
  • 求解子问题:
  • 合并子问题的解为原问题的解。

在分治法中,子问题一般是相互独立的,因此,经常通过递归调用算法来求解子问题。

拆分任务
在这里插入图片描述
在这里插入图片描述
普通线程池递归计算任务
普通线程池递归计算任务存在的问题(需要等待前面的结果)

public Long call() throws Exception { // override
    System.out.format("%s range [%d-%d] begin to compute %n",
            Thread.currentThread().getName(), lo, hi);
    long result = 0;
    if (hi - lo <= SEQUENTIAL_CUTOFF) {
        for (int i = lo; i < hi; i++)
            result += arr[i];

        System.out.format("%s range [%d-%d] begin to finished %n",
                Thread.currentThread().getName(), lo, hi);
    }
    else {
        RecursiveSumTask left = new RecursiveSumTask(executorService, arr, lo, (hi + lo) / 2);
        RecursiveSumTask right = new RecursiveSumTask(executorService, arr, (hi + lo) / 2, hi);
        Future<Long> lr = executorService.submit(left);
        Future<Long> rr = executorService.submit(right);

        result = lr.get() + rr.get();
        System.out.format("%s range [%d-%d] finished to compute %n",
                Thread.currentThread().getName(), lo, hi);
    }

    return result;
}

Fork/Join并行处理框架

Java 1.7 引入了一种新的并发框架—— Fork/Join Framework

  • 主要用于实现“分而治之”的算法,特别是分治之后递归调用的函数
  • 提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架
  • 与ThreadPool共存,并不是要替换ThreadPool

ForkJoinPool 框架主要类:
在这里插入图片描述
ForkJoinPool 实现ForkJoin的线程池 - ThreadPool

  • ForkJoinWorkerThread 实现ForkJoin的线程

ForkJoinTask 一个描述ForkJoin的抽象类 Runnable/Callable

  • RecursiveAction 无返回结果的ForkJoinTask实现Runnable
  • RecursiveTask 有返回结果的ForkJoinTask实现Callable
  • CountedCompleter 在任务完成执行后会触发执行一个自定义的钩子函数
    在这里插入图片描述
    在这里插入图片描述
    内部原理
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    应用实例 (从redis获取3万个key值)
 String keyPreFix = "foe:test:liuli";
 Map<String, String>  map = aliYunRedisService.hgetAll(keyPreFix);
        List<String>  keyList = new ArrayList<>();
        for (String key : map.keySet()) {
            keyList.add(map.get(key));
        }
        //分治
        FockJoinTaskService fockJoinTest = new     FockJoinTaskService(keyList,0,keyList.size(),aliYunRedisService);
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        Future<List<QuestionSeriesUserInfoVo>> result = forkJoinPool.submit(fockJoinTest);

/**分治任务*/
public class FockJoinTaskService extends RecursiveTask<List<QuestionSeriesUserInfoVo>> {

    AliYunRedisService aliYunRedisService;

    List<String>  keyList;

    private static final int THREAD_HOLD = 500;
    private int start;
    private int end;


    public FockJoinTaskService(List<String>  keyList, int start, int end, AliYunRedisService aliYunRedisService) {
        this.start = start;
        this.end = end;
        this.keyList = keyList;
        this.aliYunRedisService =aliYunRedisService;
    }

        @Override
        protected List<QuestionSeriesUserInfoVo> compute() {
        List<QuestionSeriesUserInfoVo> testBeanList = new ArrayList<>();
            boolean canCompute = (end - start) <= THREAD_HOLD;
            if(canCompute){
                for(int i=start ;i< end ;i++){
                    QuestionSeriesUserInfoVo questionSeriesUserInfoVo = new QuestionSeriesUserInfoVo();
                    String keyInfo = keyList.get(i);
                    if (StringUtils.isNotBlank(keyInfo)){
                        String keyInfoValue = aliYunRedisService.getAsString(keyInfo);
                        if (StringUtils.isNotBlank(keyInfo)){
                            questionSeriesUserInfoVo = JSONObject.parseObject(keyInfoValue,QuestionSeriesUserInfoVo.class);
                            testBeanList.add(questionSeriesUserInfoVo);
                        }
                    }
                }
            }else{
                int middle = (start + end) / 2;
                FockJoinTaskService left = new FockJoinTaskService(keyList,start,middle,aliYunRedisService);
                FockJoinTaskService right = new FockJoinTaskService(keyList,middle,end,aliYunRedisService);
                //执行子任务
                left.fork();
                right.fork();
                //获取子任务结果
                List<QuestionSeriesUserInfoVo> lResult = left.join();
                List<QuestionSeriesUserInfoVo> rResult = right.join();
                testBeanList.addAll(lResult);
                testBeanList.addAll(rResult);
            }
        return testBeanList;
    }

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值