专栏名称: 开发者全社区
分享和推送Java/Android方向的技术和文章,让你成为这方面的大牛,让你每天都成长一点。同时,我们也会邀请BAT的大牛分享原创!
目录
相关文章推荐
鸿洋  ·  Google 为何设计了如此难用的 ... ·  19 小时前  
stormzhang  ·  时间不多了 ·  昨天  
鸿洋  ·  Android14 WMS/AMS ... ·  昨天  
stormzhang  ·  真正该刺激的是收入 ·  2 天前  
鸿洋  ·  Android主线程锁监控的一种方案 ·  6 天前  
51好读  ›  专栏  ›  开发者全社区

Java高级:多线程之ExecutorCompletionService 源码分析

开发者全社区  · 公众号  · android  · 2017-07-20 07:43

正文


热文导读 | 点击标题阅读

移动端开发者以后的路在哪里?

吊炸天!74款APP完整源码!

2017 春季最酷、最受欢迎的 30 个 Android 库,快收藏!

作者:jijs
链接:http://www.jianshu.com/p/490f7e86e20c

概要

在ExecutorService的submit方法中可以获取返回值,通过Future的get方法,但是这个Future类存在缺陷,Future接口调用get()方法取得处理后的返回结果时具有阻塞性,也就是说调用Future的get方法时,任务没有执行完成,则get方法要一直阻塞等到任务完成为止。 这样大大的影响了系统的性能,这就是Future的最大缺点。为此,java1.5以后提供了CompletionServlice来解决这个问题。

CompletionService 接口CompletionService的功能是异步的方式,一边生产任务,一边处理完成的任务结果,这样可以将执行的任务与处理任务隔离开来进行处理,使用submit执行任务,使用塔克获取已完成的任务,并按照这些任务的完成的时间顺序来处理他们的结果。

示例

向ExecutorService 提交一组任务,哪个任务先完成,就把完成任务的返回结果打印出来。

执行结果如下:

从打印结果可以看出,这些任务是按照任务执行完成的顺序打印的,先执行完就先返回结果。

ExecutorCompletionService 源码分析

ExecutorCompletionService 类结构如下

ExecutorCompletionService 类中定义了一个QueueingFuture 的内部类,继承于FutureTask类,内部重写了FutureTask的done方法,该方法是在FutureTask任务执行完成后会调用的方法,在FutureTask中该方法未实现任何逻辑。

重写done方法,在任务处理完成后把该FutureTask任务放入到阻塞队列(BlockingQueue)中,然后我们就可以从阻塞队列中take执行完成的任务,进行想用的处理。

这里是实现ExecutorCompletionService的核心逻辑。

newTaskFor 方法

ExecutorCompletionService 支持Callable和Runnable任务

  1. 把用户提交的Callable任务转成FutureTask。

  2. 把用户提交的Runnable任务转成FutureTask。

ExecutorCompletionService 构造方法1

  1. 连接池(executor)不能为空。

  2. 判断该线程池是否AbstractExecutorService类型,如果是则赋值给aes,否则赋值null
    (aes作用:把用户提交的Callable和Runnable任务转换成FutureTask)

  3. 创建一个阻塞队列。(存放执行完成的FutureTask任务)

ExecutorCompletionService 构造方法2

该构造可以指定一个阻塞队列,其它功能同上构造方法。

submit方法

该方法可以向ExecutorCompletionService 中提交要执行的任务。
支持Callable和Runnable两种类型的任务。
如果提交的Runnable任务,则执行完后返回的结果为null。

ExecutorCompletionService支持非阻塞方式从阻塞队列中获取已完成的任务

  1. 可以通过poll方法来从阻塞队列中获取任务,如果队列为空,则直接返回null,不会阻塞当前线程。

  2. 支持等待多长时间来从阻塞队列中获取已经完成的任务。

总结

ExecutorCompletionService的实现原理是内部使用了FutureTask来实现异步的任务执行。通过一个内部类继承FutureTask,并实现了FutureTask的一个done方法。该done方法会在任务执行完成之后调用该方法,在任务执行完之后把当前的FutureTask放入到阻塞队列中。这样就实现了先执行完成的任务先存放到阻塞队列中,应用程序可以从阻塞队列中提前获取先执行完的任务

看完本文有收获?请分享给更多人

更多学习资料点击下面的“阅读原文”获取


Java和Android架构

欢迎关注我们,一起讨论技术,扫描和长按下方的二维码可快速关注我们。搜索微信公众号:JANiubility。

公众号:JANiubility