zoukankan      html  css  js  c++  java
  • Fork/Join 线程池

    简述

      Fork/Join 是 JDK 1.7 加入的新的线程池实现,它体现的是一种分治思想,适用于能够进行任务拆分的 cpu 密集型运算Fork/Join 在分治的基础上加入了多线程,可以把每个任务的分解和合并交给不同的线程来完成,进一步提升了运算效率Fork/Join 默认会创建与 cpu 核心数大小相同的线程池

    使用

      基本的使用流程就是创建任务然后交给线程池执行

      这里的任务就不是runnable和callable的对象了,得用RecursiveTaskRecursiveAction的子类,前者有返回结果,后者没有返回结果

      forkjoin线程池的分治思想和递归很类似,比如我们想要求1到n的和,若n=5时,f(5) = 5 + f(4) f(4) = 4 + f(3)以此类推可以进行一个任务的拆分

      重写的compute方法就是该递归方法

    package ThreadTest.ThreadPool;
    
    import java.util.concurrent.ForkJoinPool;
    import java.util.concurrent.RecursiveAction;
    import java.util.concurrent.RecursiveTask;
    
    public class TestFork {
        public static void main(String[] args) {
            ForkJoinPool pool = new ForkJoinPool(5);
            System.out.println(pool.invoke(new MyTask(5)));
            //f(5) = 5 + f(4) f(4) = 4 + f(3)...
        }
    }
    
    class MyTask extends RecursiveTask<Integer> {
    
        private int n;
    
        public MyTask(int n) {
            this.n = n;
        }
    
        @Override
        protected Integer compute() {
            if(n==1) return 1;//终止条件
            MyTask t1 = new MyTask(n-1);
            t1.fork();//让一个线程去执行
            Integer result = n + t1.join();//获取任务结果
            return result;
        }
    }
    sample

      任务拆分的优化,本来我们的任务拆分是这样的:

      可以看到线程的并行度很低,线程都要依赖下一个拆分任务的线程的结束才能返回

      我们可以改变任务拆分的方式:

    class AddTask1 extends RecursiveTask<Integer> {
        int n;
        public AddTask1(int n) {
            this.n = n;
        }
        @Override
        public String toString() {
            return "{" + n + '}';
        }
        @Override
        protected Integer compute() {
            // 如果 n 已经为 1,可以求得结果了
            if (n == 1) {
                log.debug("join() {}", n);
                return n;
            }
    
            // 将任务进行拆分(fork)
            AddTask1 t1 = new AddTask1(n - 1);
            t1.fork();
            log.debug("fork() {} + {}", n, t1);
    
            // 合并(join)结果
            int result = n + t1.join();
            log.debug("join() {} + {} = {}", n, t1, result);
            return result;
        }
    }
    sample2

      这样用二分的思想,从中间开始拆分,调用链就是这样了:

      可以看到t3和t2是可以并行的,这样就能提高cpu资源利用率

    一点一点积累,一点一点蜕变!
  • 相关阅读:
    80.共享内存实现进程通信
    79.cgi硬盘查询个人信息
    78.pipe多管道云端,客户端通信
    77.邮槽通信
    76.CGI编码
    strnpy函数
    POJ 1258 Agri-Net(Prim算法)
    0X7FFFFFFF,0X80000000
    Visual C++中min()和max()函数的使用
    POJ 2421 Constructing Roads(Kruskal算法)
  • 原文地址:https://www.cnblogs.com/qq2210446939/p/15165754.html
Copyright © 2011-2022 走看看