带返回结果的批量任务执行 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 类型的结果 调用带参带返回值的 ...
随机推荐
- jQuery与vue分别实现超级简单的绿色拖动验证码功能
jquery的绿色拖动验证功能 在网上看到了一个这样的问题:那种像拖动滑块匹配图形的验证方式是怎么实现的?. 突然想到实现一个简单绿色拖动验证码的功能,在网上搜了下,有一个用jquery实现的该功能代 ...
- POJ 2484 A Funny Game(智商博弈)
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6397 Accepted: 3978 Description Alice ...
- Django之URL路由系统
一 URL配置 Django 1.11版本 URLConf官方文档 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表.你就是以这 ...
- leetcode-9.回文数(水仙花数)
leetcode-9.回文数(水仙花数) 题意:给定整数,判断是否是水仙花数(回文数),返回判断结果 算法: 1.判断负数, 如果是负数直接返回false 2.将整数逐位拆解,用数组存储 3.遍历数组 ...
- C#核心基础--类的声明
C#核心基础--类的声明 类是使用关键字 class 声明的,如下面的示例所示: 访问修饰符 class 类名 { //类成员: // Methods, properties, fields, eve ...
- onclick="return function()"的使用情况
根据function的返回值,进行下一步操作,当返回值为true时,进行下一步操作,当返回值为false时,不进行操作. 例如:当在 <a href="url" onclic ...
- spring mvc 中 controller 路径配置
下图中,由于红色部分(value="/")的存在,导致 host:port/项目/dimlist 无法被映射到dimList方法,解决办法是将其去掉. package cn.bgo ...
- Linux CFS调度器之task_tick_fair处理周期性调度器--Linux进程的管理与调度(二十九)
1. CFS如何处理周期性调度器 周期性调度器的工作由scheduler_tick函数完成(定义在kernel/sched/core.c, line 2910), 在scheduler_tick中周期 ...
- UGUI ScrollRect 滑动
运行环境 Unity3D 5.3.7 p4 在我之前的博客中,写过一些Unity4.6的UGUI,现这篇是基于Unity 5.3的 推荐结构 推荐使用三层来组织,如下所示: ScrollRect :S ...
- 负载均衡(nginx、dubbo、zookeeper)
nginx dubbo zookeeper