带返回结果的批量任务执行 CompletionService
转自 :http://blog.csdn.net/lmj623565791/article/details/27250059
一般情况下,我们使用Runnable作为基本的任务表示形式,但是Runnable是一种有很大局限的抽象,run方法中只能记录日志,打印,或者把数据汇总入某个容器(一方面内存消耗大,另一方面需要控制同步,效率很大的限制),总之不能返回执行的结果;比如同时1000个任务去网络上抓取数据,然后将抓取到的数据进行处理(处理方式不定),我觉得最好的方式就是提供回调接口,把处理的方式最为回调传进去;但是现在我们有了更好的方式实现:CompletionService + Callable
Callable的call方法可以返回执行的结果;
CompletionService将Executor(线程池)和BlockingQueue(阻塞队列)结合在一起,同时使用Callable作为任务的基本单元,整个过程就是生产者不断把Callable任务放入阻塞对了,Executor作为消费者不断把任务取出来执行,并返回结果;
优势:
a、阻塞队列防止了内存中排队等待的任务过多,造成内存溢出(毕竟一般生产者速度比较快,比如爬虫准备好网址和规则,就去执行了,执行起来(消费者)还是比较慢的)
b、CompletionService可以实现,哪个任务先执行完成就返回,而不是按顺序返回,这样可以极大的提升效率;
1、CompletionService : Executor + BlockingQueue
下面看个例子:
- package com.zhy.concurrency.completionService;
- import java.util.Random;
- import java.util.concurrent.BlockingQueue;
- import java.util.concurrent.Callable;
- import java.util.concurrent.CompletionService;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.ExecutorCompletionService;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Future;
- import java.util.concurrent.LinkedBlockingDeque;
- /**
- * 将Executor和BlockingQueue功能融合在一起,可以将Callable的任务提交给它来执行, 然后使用take()方法获得已经完成的结果
- *
- * @author zhy
- *
- */
- public class CompletionServiceDemo
- {
- public static void main(String[] args) throws InterruptedException,
- ExecutionException
- {
- /**
- * 内部维护11个线程的线程池
- */
- ExecutorService exec = Executors.newFixedThreadPool(11);
- /**
- * 容量为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++)
- {
- completionService.submit(new Callable<Integer>()
- {
- @Override
- public Integer call() throws Exception
- {
- int ran = new Random().nextInt(1000);
- Thread.sleep(ran);
- System.out.println(Thread.currentThread().getName()
- + " 休息了 " + ran);
- return ran;
- }
- });
- }
- /**
- * 立即输出结果
- */
- for (int i = 0; i < 10; i++)
- {
- try
- {
- //谁最先执行完成,直接返回
- Future<Integer> f = completionService.take();
- System.out.println(f.get());
- } catch (InterruptedException e)
- {
- e.printStackTrace();
- } catch (ExecutionException e)
- {
- e.printStackTrace();
- }
- }
- exec.shutdown();
- }
- }
输出结果:
- pool-1-thread-4 休息了 52
- 52
- pool-1-thread-1 休息了 59
- 59
- pool-1-thread-10 休息了 215
- 215
- pool-1-thread-9 休息了 352
- 352
- pool-1-thread-5 休息了 389
- 389
- pool-1-thread-3 休息了 589
- 589
- pool-1-thread-2 休息了 794
- 794
- pool-1-thread-7 休息了 805
- 805
- pool-1-thread-6 休息了 909
- 909
- pool-1-thread-8 休息了 987
- 987
最先执行完成的直接返回,并不需要按任务提交的顺序执行,如果需要写个高并发的程序,且每个任务需要返回执行结果,这是个相当不错的选择!
带返回结果的批量任务执行 CompletionService的更多相关文章
- Java并发专题 带返回结果的批量任务执行 CompletionService ExecutorService.invokeAll(转)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/27250059 一般情况下,我们使用Runnable作为基本的任务表示形式,但是R ...
- Java并发专题 带返回结果的批量任务执行
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/27250059 一般情况下,我们使用Runnable作为基本的任务表示形式,但是R ...
- Java并发专题 带返回结果的批量任务运行 CompletionService ExecutorService.invokeAll
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/27250059 普通情况下,我们使用Runnable作为主要的任务表示形式,可是R ...
- java并发带返回结果的批量任务执行(CompletionService:Executor + BlockingQueue)
转载:http://www.it165.net/pro/html/201405/14551.html 一般情况下,我们使用Runnable作为基本的任务表示形式,但是Runnable是一种有很大局限的 ...
- java并发带返回结果的批量任务执行
转载:http://www.it165.net/pro/html/201405/14551.html 一般情况下,我们使用Runnable作为基本的任务表示形式,但是Runnable是一种有很大局限的 ...
- Java并发(6)带返回结果的任务执行
携带结果的任务 JDK5提供了有可返回值的任务的执行.java.util.concurrent中Callable与Futrue用以实现带返回值的任务执行. 使用Callable与Futrue与使用Ru ...
- EF5中 执行 sql语句使用Database.ExecuteSqlCommand 返回影响的行数 ; EF5执行sql查询语句 Database.SqlQuery 带返回值
一: 执行sql语句,返回受影响的行数 在mysql里面,如果没有影响,那么返回行数为 -1 ,sqlserver 里面 还没有测试过 using (var ctx = new MyDbConte ...
- 慕课网-Java入门第一季-7-3 Java 中无参带返回值方法的使用
来源:http://www.imooc.com/code/1579 如果方法不包含参数,但有返回值,我们称为无参带返回值的方法. 例如:下面的代码,定义了一个方法名为 calSum ,无参数,但返回值 ...
- Java 中带参带返回值方法的使用
如果方法既包含参数,又带有返回值,我们称为带参带返回值的方法. 例如:下面的代码,定义了一个 show 方法,带有一个参数 name ,方法执行后返回一个 String 类型的结果 调用带参带返回值的 ...
随机推荐
- CSS3效果:5种预载动画效果
实现如图所示的动画效果: 预载动画一:双旋圈 在两个不同方向旋转的圆圈.我们对内圈的转速定义了一个CSS代码,即内圈比外圈的速率快2倍.实现如图所示: html代码: <body style=& ...
- GIS开发之数据查询
在GIS开发之我们经常会用到属性查询和空间查询,特别是在数据量比较大的时候,如何提高查询效率成为一个问题 1.属性查询 对于属性查询,除了必要的建索引之外,我们还应该考虑使用字段缓存:减少查询字段,减 ...
- JMeter 关于JMeter 正则表达式提取器的一点研究
关于JMeter 正则表达式提取器的一点研究 by:授客 QQ:1033553122 1. 实验环境: JMeter 2.13 2. 添加正则表达式提取器 右键线程组->添加-> ...
- java8中Lambda表达式和Stream API
一.Lambda表达式 1.语法格式 Lambda是匿名函数,可以传递代码.使用“->”操作符,改操作符将lambda分成两部分: 左侧:指定了 Lambda 表达式需要的所有参数 右侧:指定了 ...
- 使用Java实现简单的局域网设备扫描
在产品的使用中我们一般都要设置一个配置环节,这个环节可以设定主机的IP地址等信息,但是这样配置的话使得我们的产品用起来效果不是很好,因此我想到了实现局域网IP扫描的功能,IP局域网扫描是指定IP网段获 ...
- Web前端:博客美化:四、网易云音乐单曲播放器
1.页面定制CSS代码 /*3.音乐播放器*/ .content-wrap { overflow-y: scroll; -webkit-overflow-scrolling: touch; } /* ...
- mysql之事务管理
本文内容: 什么是事务管理 事务管理操作 回滚点 默认的事务管理 首发日期:2018-04-18 什么是事务管理: 可以把一系列要执行的操作称为事务,而事务管理就是管理这些操作要么完全执行,要么完全不 ...
- 使用Visual Studio Team Services敏捷规划和项目组合管理(七)——流程定制
使用Visual Studio Team Services敏捷规划和项目组合管理(七)--流程定制 在Team Services中,可以通过流程定制工作追踪体验.流程定义了工作项跟踪系统的构建部分,以 ...
- Django之--网页展示Hello World!
上一篇:Django的安装启动完毕后,本文来试下hello world的效果~ 好吧,又开始了喜闻乐见的Hello World环节,本文使用Linux环境演示(Windows太麻烦). [root@p ...
- May 25. 2018 Week 21st Friday
Nothing for nothing. 不费力气,就一无所得. These days I am busy in compiling a lightweight communication libra ...