线程池原理(五):CompletionService
来源:互联网 发布:淘宝店铺手机怎么登陆 编辑:程序博客网 时间:2024/05/24 06:10
任务提交到线程池后,将任务的Future放到一个List中,然后遍历List,通过Future的get方法得到返回值。如果在遍历过程中get方法阻塞,即使位于List后面的Future已经完成,遍历List的线程也要继续等待,这就对效率有比较大的影响。我们希望任务结束后,返回值能够立即被获取,而不是要等待其他任务结束。
CompletionService正是为此而生,实现中通过维护一个队列保存结束任务的Future,如果有任务结束,任务的Future会保存到队列中,从该队列中一定能拿到任务的返回结果。如果没有已经完成的任务,队列为空,取结果的线程会阻塞。
CompletionService
我们先看下接口CompletionService
public interface CompletionService<V> { //提交任务 Future<V> submit(Callable<V> task); //提交任务 Future<V> submit(Runnable task, V result); //取下一个已经结束任务的返回值,如果没有则等待 //注意,该方法响应中断 Future<V> take() throws InterruptedException; //取下一个已经结束任务的返回值,如果没有返回null Future<V> poll(); //取下一个已经结束任务的返回值,如果没有最多等待timeout时间 Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException;}
该接口很简单,主要就是take、pool方法,取已经完成任务的返回值,接着我们看下jdk中该接口的实现类,ExecutorCompletionService。
ExecutorCompletionService
该类实现了CompletionService,维护一个阻塞队列(默认为LinkedBlockingQueue)保存已经完成的任务Future。worker执行完某个任务时会将任务的Future添加到该阻塞队列,阻塞队列按任务的完成顺序保存了任务的Future。取任务时,如果阻塞队列为空,说明没有已经完成的任务。看下该该类的实现:
public class ExecutorCompletionService<V> implements CompletionService<V> { //任务的执行委托给了executor private final Executor executor; //如果executor继承自AbstractExecutorService,aes和executor指向同一个对象 //否则aes为空 private final AbstractExecutorService aes; //保存完成任务的Future private final BlockingQueue<Future<V>> completionQueue; //CompletionService执行的任务继承了FutureTask,重写了done方法 //每当任务结束后将任务的Future加到completionQueue中 private class QueueingFuture extends FutureTask<Void> { QueueingFuture(RunnableFuture<V> task) { super(task, null); this.task = task; } //任务结束后将Future加到队列中 protected void done() { completionQueue.add(task); } private final Future<V> task; } //包装成FutureTask private RunnableFuture<V> newTaskFor(Callable<V> task) { if (aes == null) return new FutureTask<V>(task); else return aes.newTaskFor(task); } //包装成FutureTask private RunnableFuture<V> newTaskFor(Runnable task, V result) { if (aes == null) return new FutureTask<V>(task, result); else return aes.newTaskFor(task, result); } //构造函数,指定执行器executor public ExecutorCompletionService(Executor executor) { if (executor == null) throw new NullPointerException(); this.executor = executor; this.aes = (executor instanceof AbstractExecutorService) ? (AbstractExecutorService) executor : null; //用LinkedBlockingQueue保存完成任务的Future this.completionQueue = new LinkedBlockingQueue<Future<V>>(); } //构造函数,指定executor和queue public ExecutorCompletionService(Executor executor, BlockingQueue<Future<V>> completionQueue) { if (executor == null || completionQueue == null) throw new NullPointerException(); this.executor = executor; this.aes = (executor instanceof AbstractExecutorService) ? (AbstractExecutorService) executor : null; this.completionQueue = completionQueue; } //提交任务,将任务包装成QueueingFuture后交给executor执行 public Future<V> submit(Callable<V> task) { if (task == null) throw new NullPointerException(); RunnableFuture<V> f = newTaskFor(task); executor.execute(new QueueingFuture(f)); return f; } public Future<V> submit(Runnable task, V result) { if (task == null) throw new NullPointerException(); RunnableFuture<V> f = newTaskFor(task, result); executor.execute(new QueueingFuture(f)); return f; } //从队列中取已经结束任务的返回值,如果队列为空则阻塞 public Future<V> take() throws InterruptedException { return completionQueue.take(); } //从队列中取已经结束任务的返回值,如果队列为空返回null public Future<V> poll() { return completionQueue.poll(); } //从队列中取已经结束任务的返回值,如果超时,返回空 public Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException { return completionQueue.poll(timeout, unit); }}
ExecutorCompletionService实现也很简单,主要是QueueingFuture,将QueueingFuture作为任务来执行,QueueingFuture继承FutureTask,重写了done方法。done方法在FutureTask中是一个空方法,留给子类重写。任务完成后会调用done方法,将任务的Future加到队列中。
- 线程池原理(五):CompletionService
- Java线程池CompletionService的简单应用
- 线程池中CompletionService的应用
- (android实战)线程池实现,并通过CompletionService,来实现反馈处理(转载)
- Java线程之CompletionService
- Java线程之CompletionService
- Java线程 CompletionService
- 线程池实现,并通过CompletionService,来实现反馈处理
- 多线程Demo-CompletionService收集线程池执行结果
- CompletionService 简介(异步)
- CompletionService
- CompletionService
- CompletionService
- CompletionService
- CompletionService
- CompletionService
- CompletionService
- CompletionService
- bzoj1191 [HNOI2006]超级英雄Hero
- impress.js
- C#事件中sender的小用法
- 下拉选择框
- hystrix 1.5.13 学习笔记
- 线程池原理(五):CompletionService
- 10款优秀的vim插件
- Java反射
- MySQL 数据库优化的八种方式
- Oracle 11g利用DBCA创建数据库
- ubuntu更换阿里源
- IOS 元素定位工具
- InfoSphere DataStage 运行时列扩展(RCP)在 ETL 中的应用
- Pat(A) 1094. The Largest Generation (25)