zoukankan      html  css  js  c++  java
  • java并发编程-Executor框架 + Callable + Future

    from: https://www.cnblogs.com/shipengzhi/articles/2067154.html

    import java.util.concurrent.*;
    public class ConcurrentCalculator2 { //from: https://www.cnblogs.com/shipengzhi/articles/2067154.html
        private ExecutorService executorService;
        private CompletionService<Long> completionService;
        private int cpuCoreNumber;
    
        public ConcurrentCalculator2() {
            cpuCoreNumber = Runtime.getRuntime().availableProcessors();
            executorService = Executors.newFixedThreadPool(cpuCoreNumber);
            completionService = new ExecutorCompletionService<Long>(executorService);
        }
    
        public Long sum(final int[] numbers) {
            for (int i = 0; i < cpuCoreNumber; i++) {               //(页数)根据CPU核心个数拆分任务,创建FutureTask并提交到Executor
                int increment = numbers.length / cpuCoreNumber + 1; //(每页多少条)
                int start = increment * i;                          //首条数据-->当前页    的
                int end = increment * i + increment;                //首条数据-->(当前页+1)的
                if (end > numbers.length)
                    end = numbers.length;
                SumCalculator subCalc = new SumCalculator(numbers, start, end, (i+1));
                if (!executorService.isShutdown()) {
                    completionService.submit(subCalc);
                }
            }
            System.out.println("所有计算任务提交完毕, 主线程接着干其他事情!");
            return getResult();
        }
    
        public Long getResult() { //迭代每个只任务,获得部分和,相加返回
            Long result = 0l;
            int index =0;
            System.out.println("-->2-"+ Thread.currentThread().getName()+"线程 List<Future<Long>>集合中的第一个元素开始遍历之前【就开始 全部执行掉MyCallable构造方法(不一定按集合内部顺序)!】");
            for (int i = 0; i < cpuCoreNumber; i++) {
                try {
                    index++;
                    Long subSum = completionService.take().get();
                    System.out.println("-->4-"+Thread.currentThread().getName()+"线程 "+"-List<Future<Long>>集合遍历ing(一定按集合内部顺序)【有时候3和4会<成对>交叉执行】-- 打印第:"+index+"页累计的和:" + subSum);
                    result += subSum;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("-->5-总结-->线程的实现方法总是先一步于List<Future<Long>>的遍历(线程的impl分页计算各页的总和,List<Future>负责把所有页的和累加!");
            return result;
    
        }
    
        public void close() {
            executorService.shutdown();
        }
    
        class SumCalculator implements Callable<Long> {//Runnable
            private int[] numbers;
            private int start;
            private int end;
            private int index;
    
            public SumCalculator(final int[] numbers, int start, int end, int index) {
                this.numbers = numbers;
                this.start = start;
                this.end = end;
                this.index = index;
                System.out.println("-->1-"+Thread.currentThread().getName() +"线程-生成子线程计算任务(调用构造函数)第 "+ index +"次");
            }
    
            @Override
            public Long call() throws Exception {
                Long sum = 0l;
                for (int i = start; i < end; i++) {
                    sum += numbers[i];
                }
                //子线程-->休眠5秒钟,观察主线程行为,预期的结果是主线程会继续执行,到要取得FutureTask的结果是等待直至完成。
                Thread.sleep(3000);
    
                System.out.println("-->3-" + Thread.currentThread().getName() + "线程执行计算任务 打印current数据:" +"startIndex:"+ start + ";endIndex:" + end+ ";sum:" + "=" + sum);
                return sum;
            }
        }
        public static void main(String[] args) {
            int[] numbers = new int[] { 0, 1, 2  };
            ConcurrentCalculator2 calculator = new ConcurrentCalculator2();
            Long sum = calculator.sum(numbers);
            System.out.println("-->10-res:"+sum);
            calculator.close();
        }
    
    
        /**
    
         * Callable 和 Future接口
    
         * Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。
    
         * Callable和Runnable有几点不同:
    
         * (1)Callable规定的方法是call(),而Runnable规定的方法是run().
    
         * (2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
    
         * (3)call()方法可抛出异常,而run()方法是不能抛出异常的。
    
         * (4)运行Callable任务可拿到一个Future对象,
    
         * Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。
    
         * 通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。
    
         */
    }
  • 相关阅读:
    SpringBoot之集成slf4j日志框架
    Maven项目优势
    Idea操作技巧
    Nginx服务器之负载均衡策略(6种)
    Git操作规范
    Mybatis之Tk
    MyEclipse取消验证Js的两种方法
    文件异步上传,多文件上传插件uploadify
    EasyMock的使用
    jquery 中post 、get的同步问题,从外部获取返回数据
  • 原文地址:https://www.cnblogs.com/hahajava/p/9808873.html
Copyright © 2011-2022 走看看