Java并发编程(八)——批量获取多条线程的执行结果

来源:互联网 发布:java课程体系 编辑:程序博客网 时间:2024/05/17 13:40

摘自:http://blog.csdn.net/u010425776/article/details/54580710

目录(?)[+]

  1. 方法一自己维护返回结果
  2. 方法二使用ExecutorService的invokeAll函数
  3. 方法三使用CompletionService

当向线程池提交callable任务后,我们可能需要一次性获取所有返回结果,有三种处理方法。

方法一:自己维护返回结果

// 创建一个线程池ExecutorService executorService = Executors.newFixedThreadPool(10);// 存储执行结果的ListList<Future<String>> results = new ArrayList<Future<String>>();// 提交10个任务for ( int i=0; i<10; i++ ) {    Future<String> result = executorService.submit( new Callable<String>(){        public String call(){            int sleepTime = new Random().nextInt(1000);            Thread.sleep(sleepTime);            return "线程"+i+"睡了"+sleepTime+"秒";        }    } );    // 将执行结果存入results中    results.add( result );}// 获取10个任务的返回结果for ( int i=0; i<10; i++ ) {    // 获取包含返回结果的future对象    Future<String> future = results.get(i);    // 从future中取出执行结果(若尚未返回结果,则get方法被阻塞,直到结果被返回为止)    String result = future.get();    System.out.println(result);}

      此方法的弊端:

      1. 需要自己创建容器维护所有的返回结果,比较麻烦;
      2. 从list中遍历的每个Future对象并不一定处于完成状态,这时调用get()方法就会被阻塞住,如果系统是设计成每个线程完成后就能根据其结果继续做后面的事,这样对于处于list后面的但是先完成的线程就会增加了额外的等待时间。

      方法二:使用ExecutorService的invokeAll函数

      本方法能解决第一个弊端,即并不需要自己去维护一个存储返回结果的容器。当我们需要获取线程池所有的返回结果时,只需调用invokeAll函数即可。
      但是,这种方式需要你自己去维护一个用于存储任务的容器。

      // 创建一个线程池ExecutorService executorService = Executors.newFixedThreadPool(10);// 创建存储任务的容器List<Callable<String>> tasks = new ArrayList<Callable<String>>();// 提交10个任务for ( int i=0; i<10; i++ ) {    Callable<String> task = new Callable<String>(){        public String call(){            int sleepTime = new Random().nextInt(1000);            Thread.sleep(sleepTime);            return "线程"+i+"睡了"+sleepTime+"秒";        }    };    executorService.submit( task );    // 将task添加进任务队列    tasks.add( task );}// 获取10个任务的返回结果List<Future<String>> results = executorService.invokeAll( tasks );// 输出结果for ( int i=0; i<10; i++ ) {    // 获取包含返回结果的future对象    Future<String> future = results.get(i);    // 从future中取出执行结果(若尚未返回结果,则get方法被阻塞,直到结果被返回为止)    String result = future.get();    System.out.println(result);}

          方法三:使用CompletionService

          CompletionService内部维护了一个阻塞队列,只有执行完成的任务结果才会被放入该队列,这样就确保执行时间较短的任务率先被存入阻塞队列中。

          ExecutorService exec = Executors.newFixedThreadPool(10);final BlockingQueue<Future<Integer>> queue = new LinkedBlockingDeque<Future<Integer>>(                  10);          //实例化CompletionService          final CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(                  exec, queue); // 提交10个任务for ( int i=0; i<10; i++ ) {    executorService.submit( new Callable<String>(){        public String call(){            int sleepTime = new Random().nextInt(1000);            Thread.sleep(sleepTime);            return "线程"+i+"睡了"+sleepTime+"秒";        }    } );}// 输出结果for ( int i=0; i<10; i++ ) {    // 获取包含返回结果的future对象(若整个阻塞队列中还没有一条线程返回结果,那么调用take将会被阻塞,当然你可以调用poll,不会被阻塞,若没有结果会返回null,poll和take返回正确的结果后会将该结果从队列中删除)    Future<String> future = completionService.take();    // 从future中取出执行结果,这里存储的future已经拥有执行结果,get不会被阻塞    String result = future.get();    System.out.println(result);}
              阅读全文
              0 0
              原创粉丝点击
              热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 喜用神互相克害怎么办? 姓名总格不好怎么办 姓名学里人格不好怎么办 买家订单下不了怎么办 公积金不够月供怎么办 房贷担保费没交怎么办 营业执照过期1年怎么办 营业执照和公章丢失怎么办 个体户怎么办对公账户 公章法人章丢失怎么办 广州买房没有社保怎么办 辞职后计生关系怎么办 广州换工作社保怎么办 学校更名了盖章怎么办 工商注册资金没有交怎么办 住公司宿舍怎么办居住证 住在公司宿舍怎么办居住证 滴滴没有的车型怎么办 假的租房合同怎么办 代注册公司被骗怎么办 公司跨区迁址怎么办 公司搬走注册地怎么办 注册公司没有房产证怎么办 公司不运营了怎么办 公司注销了账户怎么办 租户不变更地址怎么办 营业执照忘审了怎么办 工商营业执照年检过期怎么办 个体营业执照没有年报怎么办? 个体工商户一年没有申报怎么办 个体工商户逾期未申报怎么办 个体户没报税过怎么办 农业银行证书过期了怎么办 ca证书丢了怎么办 ca证书被锁怎么办 上个月忘记清卡怎么办 财务人员进入税务黑名单怎么办 社保本丢了怎么办 贷款车辆登记证书怎么办 发票薄丢了怎么办? 汽车发票丢了怎么办