forkjoin并行框架实践

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_20009015/article/details/89913091
 @Override
    public List<TaxForeDTO> getTaxForeForkJoin(List<String> organizeId, String uid, Date Begin, Date end)
            throws Exception {
        Long begintime=System.currentTimeMillis();
        //cpu+io总耗时23秒 io时间21秒
        //最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目
        //21/2+1
        int nums= 11*Runtime.getRuntime().availableProcessors();
        log.info("线程数{}",organizeId.size());
      //  ForkJoinPool forkjoinPool = new ForkJoinPool(nums);
        ForkJoinPool forkjoinPool = new ForkJoinPool(organizeId.size());
        //生成一个计算任务
        ForkJoinTaskExample task = new ForkJoinTaskExample(organizeId, uid,Begin,end);

        //执行一个任务
        Future<List<TaxForeDTO>> result = forkjoinPool.submit(task);

        List<TaxForeDTO> list=new ArrayList<>();
        try {
            list=result.get();
            log.info("result:{}", list);
        } catch (Exception e) {
            log.error("exception", e);
        }

        Long endtime=System.currentTimeMillis();
        log.info("预测表并行开始时间{},结束时间{},总耗时{},秒数{}", begintime,endtime, endtime-begintime,(endtime-begintime)/1000.0f);
        return list;
    }

     class ForkJoinTaskExample extends RecursiveTask<List<TaxForeDTO>> {

        public  final int threshold = 2;

        private List<String> organizeId;
        private String uid;
        private  Date Begin;
        private Date endDate;
        private int start;
        private int end;

        public ForkJoinTaskExample(List<String> organizeId, String uid, Date begin, Date end) {
            this.organizeId = organizeId;
            this.uid = uid;
            this.Begin = begin;
            this.endDate = end;
            this.start=0;
            this.end=organizeId.size()-1;

        }

        @Override
        protected List<TaxForeDTO> compute() {
            List<TaxForeDTO> sum=new ArrayList<>();
            //如果任务足够小就计算任务
            boolean canCompute = (end - start) <=threshold;
            if (canCompute) {
                try {
                    sum.addAll(getTaxFore(organizeId.subList(start,end),uid,Begin,endDate));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                // 如果任务大于阈值,就分裂成两个子任务计算
                int middle = (start + end) / 2;
                ForkJoinTaskExample leftTask = new ForkJoinTaskExample(organizeId.subList(start,middle),uid,Begin,endDate);
                ForkJoinTaskExample rightTask = new ForkJoinTaskExample(organizeId.subList(middle+1,end),uid,Begin,endDate);

                // 执行子任务
                leftTask.fork();
                rightTask.fork();

                // 等待任务执行结束合并其结果
                List<TaxForeDTO>  leftResult = leftTask.join();
                List<TaxForeDTO>  rightResult = rightTask.join();

                // 合并子任务
                sum.addAll(leftResult);
                sum.addAll(rightResult);
            }
            return sum;
        }
    }

这里注意下 ,想查询sql这种,因为发起请求之后 要等待数据库的返回,大部分时间其实是在等待io。 这种频繁等待io的操作 是io密集型,这个时候设置的线程数
可以粗略的设置成2*N (N为cpu核心数 可以用Runtime.getRuntime().availableProcessors() 获取) ,或者设置成(总时间/cpu时间)*N 总时间是指cpu时间+等待io时间

如果是cpu密集型任务,则线程数设置为N+1就差不多了,再多 也会因为上下文切换而浪费时间,而且 cpu也不堪重负。

猜你喜欢

转载自blog.csdn.net/qq_20009015/article/details/89913091