Java并发之JDK并发包(3)

实战Java高并发程序设计笔记


分而治之:Fork/Join框架

  1. ForkJoinPool线程池,对于fork而言并不急于开启线程,而是提交给ForkJoinPool线程池处理,以节省资源。使用ForkJoinPool进行数据处理的总机构图如下


    Fork/join执行逻辑
  2. ForkJoinPool 简单例子:计算1到10000的和
    private static final int THRESHOLD = 1000;
    public static void main(String args[]) throws ExecutionException, InterruptedException {
        System.out.println(System.currentTimeMillis() / 1000);
        System.out.println(sum(1, 10000));
        System.out.println(System.currentTimeMillis() / 1000);
        System.out.println("¥¥¥¥¥¥¥¥¥");
        System.out.println(System.currentTimeMillis() / 1000);
        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask<Long> task = pool.submit(new CountTask(1, 10000));
        System.out.println( task.get());
        System.out.println(System.currentTimeMillis() / 1000);
    }
public static long sum(long start, long end) {
        if (end - start + 1 > THRESHOLD) {
            return sum(start, (start + end) / 2) + sum((start + end) / 2, end);
        } else {
            long sum = 0;
            for (long i = start; i <= end; i++) {
                sum += i;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return sum;
        }
    }
static class CountTask extends RecursiveTask<Long> {
        private long end;
        private long start;

        public CountTask(long start, long end) {
            this.end = end;
            this.start = start;
        }

        @Override
        protected Long compute() {
            if (end - start + 1 > THRESHOLD) {
                CountTask task1 = new CountTask(start, (start + end) / 2);
                CountTask task2 = new CountTask((start + end) / 2, end);
                task1.fork();
                task2.fork();
                return task1.join() + task2.join();
            } else {
                long sum = 0;
                for (long i = start; i <= end; i++) {
                    sum += i;
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return sum;
            }
        }
    }
  • 运行结构:
    1480090749
    50080000
    1480090765
    ¥¥¥¥¥¥¥¥¥
    1480090765
    50080000
    1480090768
    可以看出,sum 计算需要16秒,而使用ForkJoinPool 仅仅需要3秒
  • 使用ForkJoin时,任务的划分层次不能太深否则可能出现两种情况
    • 系统内线程数量越来越多。导致性能严重下降
    • 函数的调用层次变得很深,最终导致堆栈溢出
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Java经典问题算法大全 /*【程序1】 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子...
    赵宇_阿特奇阅读 1,908评论 0 2
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,765评论 18 399
  • 【程序1】 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔...
    叶总韩阅读 5,165评论 0 41
  • 看, 妈妈的手, 硬硬的,涩涩的 岁月静好,老了沧桑 软软的,暖暖的 生活再苦,护了小家 这是一个臃肿的手 辛辛苦...
    花落谁家的孩子阅读 175评论 1 3
  • 一场说走就走的旅行,这句话刚冒尖的时候,我就念叨着要为自己放纵一把,终于过了n久之后,我和闺蜜踏上了南下的旅程。对...
    幽谷清香阅读 219评论 0 1