携带结果的任务callable与future
来源:互联网 发布:线切割如何编程链轮 编辑:程序博客网 时间:2024/05/01 19:13
Executor框架使用Runnable作为其基本任务表示形式。Runnable是一种有很大局限的抽象,它不能返回一个值或者抛出一个受检查的异常。
但是许多任务实际上都是存在延迟的计算,比如执行数据库查询,从网络上获取资源,或者计算某个复杂的功能。对于这些任务,就要Callable来显身手了。
public interface Callable<V>{ V call() throws Exception;}
Future表示一个任务的生命周期,并提供了相应的方法来判断是否已经完成或者取消,以及获取任务的结果和取消任务等。
public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;}
ExecutorService中所有submit方法都将返回一个Future,从而将一个Runnable或Callable提交给Executor,并得到一个Future来获得任务执行结果或者取消任务。
示例:使用Future实现页面渲染器
public class FutureRenderer { private final ExecutorService executorService = Executors.newFixedThreadPool(5); public void renderPage(CharSequence source) { final List<ImageInfo> imageInfoList = scanForImageInfo(source); Callable<List<ImageData>> task = new Callable<List<ImageData>>() { public List<ImageData> call() throws Exception { List<ImageData> result = new ArrayList<ImageData>(); for (ImageInfo imageInfo:imageInfoList) result.add(imageInfo.downloadImage()); return null; } }; Future<List<ImageData>> future = executorService.submit(task); renderText(source); try { List<ImageData> imageDatas = future.get(); for (ImageData data : imageDatas) { renderImage(data); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); future.cancel(true); } catch (ExecutionException e) { e.printStackTrace(); } }}
get方法的行为取决于任务的状态(尚未开始、正在运行、已完成)。如果任务已经完成,那么get会立即返回或者抛出一个Exception,如果任务没有完成,那么get将阻塞并直到任务完成。
还可以显式地为某个指定的Runnable或Callable实例化一个FutureTask(由于FutureTask实现了Runnable,因此可以将它提交给Executor来执行或者直接调用它的run方法)。
ExecutorService executorService = Executors.newFixedThreadPool(5); FutureTask futureTask = new FutureTask(new Callable() { @Override public Object call() throws Exception { return null; }});executorService.submit(futureTask);//futureTask.run();
CompletionService
CompletionService将Executor和BlockingQueue的功能融合在一起。你可以将Callable任务提交给它来执行,然后使用类似于队列操作的take和poll等方法来获得已完成的结果。
示例:使用CompletionService实现页面渲染器
public class Renderer { private final ExecutorService executorService; public Renderer(ExecutorService executorService) { this.executorService = executorService; } public void renderPage(CharSequence source) { final List<ImageInfo> imageInfoList = scanForImageInfo(source); CompletionService<ImageData> completionService = new ExecutorCompletionService<ImageData>(executorService); for (final ImageInfo imageInfo : imageInfoList) { completionService.submit(new Callable<ImageData>() { public ImageData call() throws Exception { return imageInfo.downloadImage(); } }); } renderText(source); try { for (int i = 0, n = imageInfoList.size(); i < n; i++) { Future<ImageData> f = completionService.take(); ImageData imageData = f.get(); renderImage(data); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); future.cancel(true); } catch (ExecutionException e) { e.printStackTrace(); } }}
以上的代码从两个方面提高了页面渲染器的性能:
1. 为每一幅图像的下载都创建一个独立任务,并在线程池中执行它们,从而将串行的下载过程转换为并行的过程:这将减少下载所有图像的总时间。
2. 通过从CompletionService中获取结果以及使每张图片下载完成后立刻显示出来,能使用户获得一个更加动态和更加响应性的用户界面。
可以看摘取的部分源码:
public class ExecutorCompletionService<V> implements CompletionService<V> { private final Executor executor; private final AbstractExecutorService aes; private final BlockingQueue<Future<V>> completionQueue; /** * FutureTask extension to enqueue upon completion */ private class QueueingFuture extends FutureTask<Void> { QueueingFuture(RunnableFuture<V> task) { super(task, null); this.task = task; } protected void done() { completionQueue.add(task); } private final Future<V> task; } public ExecutorCompletionService(Executor executor) { if (executor == null) throw new NullPointerException(); this.executor = executor; this.aes = (executor instanceof AbstractExecutorService) ? (AbstractExecutorService) executor : null; this.completionQueue = new LinkedBlockingQueue<Future<V>>(); } 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; } //...}
ExecutorCompletionService实现了CompletionService,并将计算部分委托给一个Executor。在构造函数中创建一个BlockingQueue来保存计算完成的结果。
Callable和Future总是如影随形,通过一个submit方法连接起来,使任务携带结果并随时取出结果成为可能。
- 携带结果的任务callable与future
- 多线程任务Callable与Future或FutureTask的使用
- Callable与Future的应用
- Callable与Future的介绍
- Callable与Future的介绍
- Callable与Future的介绍
- Callable与Future的介绍
- Callable与Future的介绍
- Callable与Future的介绍
- Callable与Future的介绍
- Callable与Future的介绍
- Callable与Future的介绍
- Callable与Future的介绍
- Callable与Future的介绍
- Callable与Future的介绍
- Callable与Future的介绍
- Callable与Future的介绍
- Callable与Future的介绍
- 网络攻防之——wireshark的使用
- CSDN安家落户
- test
- 最新2017(Android)安卓面试题级答案(精选版)
- 1001
- 携带结果的任务callable与future
- 鸣人与佐助 poj
- Evaluate Division
- Linux_C笔记day05
- iOS 安全模型浅析(二) ---- 沙盒机制
- 烤鸡
- HTTP协议GET和POST请求对比
- EXCEL大数据导出(100W条)
- CodeForces