线程 Thread ExecuteService ForkJoinPool 的笔记

jdk1.5前用

Thread

jdk1.5出现了

ExecuteService

从接口的使用便利程度上远胜Thread,更不用说在java.util.concurrent包中的各种线程池,Future类和Lock等便利工具,由于ExecuteService是接口,面向接口编程的实现只需要实现该接口即可。

{
   private ExecuteService executeService;
   private int parallism;
   // 构造函数
   public xxxx(){
      parallism = Runtime.getRuntime().avaliableProcessors();// 线程池个数,默认cpu的核心数
      executeService = Executors.newFixedPoolThread(parallism);
   }

   //处理计算任务的线程
    private static class SumTask implements Callable<Long> {
        private long[] numbers;
        private int from;
        private int to;

        public SumTask(long[] numbers, int from, int to) {
            this.numbers = numbers;
            this.from = from;
            this.to = to;
        }

        @Override
        public Long call() {
            long total = 0;
            for (int i = from; i <= to; i++) {
                total += numbers[i];
            }
            return total;
        }
    }


    @Override
    public long sumUp(long[] numbers) {
        List<Future<Long>> results = new ArrayList<>();

        // 把任务分解为 n 份,交给 n 个线程处理   4核心 就等分成4份呗
        // 然后把每一份都扔个一个SumTask线程 进行处理
        int part = numbers.length / parallism;
        for (int i = 0; i < parallism; i++) {
            int from = i * part; //开始位置
            int to = (i == parallism - 1) ? numbers.length - 1 : (i + 1) * part - 1; //结束位置

            //扔给线程池计算
            results.add(pool.submit(new SumTask(numbers, from, to)));
        }

        // 把每个线程的结果相加,得到最终结果 get()方法 是阻塞的
        // 优化方案:可以采用CompletableFuture来优化  JDK1.8的新特性
        long total = 0L;
        for (Future<Long> f : results) {
            try {
                total += f.get();
            } catch (Exception ignore) {
            }
        }

        return total;
    }
}

ForkJoinPool

是ExecuteService的补充,不是替代。

ExecuteSerivice是所有核心线程共享一个队列,当一个任务执行完成就会自动从队列中取出任务执行,而ForkJoinPool强调的是工作窃取算法。就是线程任务执行完成后会寻找未被执行的任务并且执行任务。

区别在于ForkJoinPool的分而治之的方法。ForkJoinPool会把任务递归细分成许多更小的任务,并且把任务的结果返回执行。而ExecuteService也可以实现这个方法,只是写的代码更麻烦一些。而ForkJoinPool的fork()方法为执行线程,join()为返回的结果。


{
   private ForkJoinPool pool ;

 //执行任务RecursiveTask:有返回值  RecursiveAction:无返回值
    private static class SumTask extends RecursiveTask<Long> {
        private long[] numbers;
        private int from;
        private int to;

        public SumTask(long[] numbers, int from, int to) {
            this.numbers = numbers;
            this.from = from;
            this.to = to;
        }

        //此方法为ForkJoin的核心方法:对任务进行拆分  拆分的好坏决定了效率的高低
        @Override
        protected Long compute() {

            // 当需要计算的数字个数小于6时,直接采用for loop方式计算结果
            if (to - from < 6) {
                long total = 0;
                for (int i = from; i <= to; i++) {
                    total += numbers[i];
                }
                return total;
            } else { // 否则,把任务一分为二,递归拆分(注意此处有递归)到底拆分成多少分 需要根据具体情况而定
                int middle = (from + to) / 2;
                SumTask taskLeft = new SumTask(numbers, from, middle);
                SumTask taskRight = new SumTask(numbers, middle + 1, to);
                taskLeft.fork();
                taskRight.fork();
                return taskLeft.join() + taskRight.join();
            }
        }
    }

 // 构造函数
  public xxxx(){
       pool = new ForkJoinPool();
  }
   public long sumUp(long[] numbers) {
       Long result = pool.invoke(new SumTask(numbers, 0, numbers.length - 1));
       pool.shutdown();
       return result;
   }
}

用ForkJoinPool的场景是 :计算数量密集型的任务。

java自学网站

ForkJoinPool参考博客网址

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值