Java并发之JDK并发包(3)

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


分而治之:Fork/Join框架

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


    Java并发之JDK并发包(3)_第1张图片
    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 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 {
        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并发之JDK并发包(3))