源码翻译师1 Android-Lite-Go(Part2)

(2)Java Executor框架
参考:
Java Executor框架

Executor框架是指java5中引入的一系列并发库中与executor相关的功能类,包括Executor、Executors、ExecutorService、CompletionService、Future、Callable等。通过学习Executor框架能够更加清楚明晰作者的写作思路和来源。


Class Executor

开始的开始 Executor

public interface Executor {
    void execute(Runnable command); 
}

Executor接口是Executor框架中最基础的部分,定义了一个用于执行Runnable的execute方法。它没有直接的实现类,有一个重要的子接口ExecutorService。

ExecutorService
ExecutorService接口继承自Executor接口,定义了终止、提交任务、跟踪任务返回结果等方法。

Runnable、Callable、Future

// 实现Runnable接口的类将被Thread执行,表示一个基本的任务
public interface Runnable {
    // run方法就是它所有的内容,就是实际执行的任务
    public abstract void run();
}

// Callable同样是任务,与Runnable接口的区别在于它接收泛型,同时它执行任务后带有返回内容
public interface Callable<V> {
    // 相对于run方法的带有返回值的call方法
    V call() throws Exception;
}

// Future代表异步任务的执行结果
public interface Future<V> {

    /**
     * 尝试取消一个任务,如果这个任务不能被取消(通常是因为已经执行完了),返回false,否则返回true。
     */
    boolean cancel(boolean mayInterruptIfRunning);

    /**
     * 返回代表的任务是否在完成之前被取消了
     */
    boolean isCancelled();

    /**
     * 如果任务已经完成,返回true
     */
    boolean isDone();

    /**
     * 获取异步任务的执行结果(如果任务没执行完将等待)
     */
    V get() throws InterruptedException, ExecutionException;

    /**
     * 获取异步任务的执行结果(有最常等待时间的限制)
     *
     *  timeout表示等待的时间,unit是它时间单位
     */
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

ScheduledFuture继承自Future和Delayed接口,自身没有添加方法。Delayed接口定义了一个获取剩余延迟的方法。

ExecutorService有一个子接口ScheduledExecutorService和一个抽象实现类AbstractExecutorService。

ScheduledExecutorService
可以安排指定时间或周期性的执行任务的ExecutorService

// 可以安排指定时间或周期性的执行任务的ExecutorService
public interface ScheduledExecutorService extends ExecutorService {
    /**
     * 在指定延迟后执行一个任务,只执行一次
     */
    public ScheduledFuture<?> schedule(Runnable command,
                       long delay, TimeUnit unit);
    /**
     * 与上面的方法相同,只是接受的是Callable任务
     */
    public <V> ScheduledFuture<V> schedule(Callable<V> callable,
                       long delay, TimeUnit unit);
    /**
     * 创建并执行一个周期性的任务,在initialDelay延迟后每间隔period个单位执行一次,时间单位都是unit
     * 每次执行任务的时间点是initialDelay, initialDelay+period, initialDelay + 2 * period...
     */
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                          long initialDelay,
                          long period,
                          TimeUnit unit);
    /**
     * 创建并执行一个周期性的任务,在initialDelay延迟后开始执行,在执行结束后再延迟delay个单位开始执行下一次任务,时间单位都是unit
     * 每次执行任务的时间点是initialDelay, initialDelay+(任务运行时间+delay), initialDelay + 2 * (任务运行时间+delay)...
     */
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                             long initialDelay,
                             long delay,
                             TimeUnit unit);
}

AbstractExecutorService
看到AbstractExecutorService的时候,基本就能找到一点痕迹了,LiteGo的核心代码有一些都参照了它的写法。
我们先来了解下下面三个概念:

  • RunnableFuture继承自Future和Runnable,只有一个run()方法。RunnableFuture接口看上去就像是Future和Runnable两个接口的组合。
public interface RunnableFuture<V> extends Runnable, Future<V> {    
        void run();
}
  • FutureTask类实现了RunnableFuture接口,除了实现了Future和Runnable中的方法外,它还有自己的方法。
  • ExecutorCompletionService实现了CompletionService接口,将结果从复杂的一部分物种解耦出来。

ThreadPoolExecutor
ThreadPoolExecutor继承自AbstractExecutorService。

ScheduledThreadPoolExecutor
它继承自ThreadPoolExecutor并实现了ScheduledExecutorService接口。

Executors
Executors中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory
和 Callable
类的工厂和实用方法。

  • newFixedThreadPool
    创建一个定长的线程池。达到最大线程数后,线程数不再增长。
    如果一个线程由于非预期Exception而结束,线程池会补充一个新的线程。
  • newCachedThreadPool
    创建一个可缓存的线程池。当池长度超过处理需求时,可以回收空闲的线程。
  • newSingleThreadPool
    创建一个单线程executor。
  • newScheduledThreadPool
    创建一个定长的线程池,而且支持定时的以及周期性的任务执行。
    类似于Timer。但是,Timer是基于绝对时间,对系统时钟的改变是敏感的,而ScheduledThreadPoolExecutor只支持相对时间。

与Timer比较

  1. Timer是创建唯一的线程来执行所有的timer任务。如果一个任务超时了,会导致其他的TimerTask时间准确性出问题。
  2. 如果TimerTask抛出uncheck 异常,Timer将会产生无法预料的行为。因此,ScheduledThreadPoolExecutor可以完全代替Timer。

(3)LinkedList 和 ArrayList
参考链接
因为平时我们大多使用的是动态数组ArrayList,对LinkedList并不是那么的熟悉,这里探究一下它们的区别和源码中为什么要使用LinkedList。

LinkedList和ArrayList都实现了List接口,但是它们的工作原理却不一样。它们之间最主要的区别在于ArrayList是可改变大小的数组,而LinkedList是双向链接串列(doubly LinkedList)。

  • 因为Array是基于索引(index)的数据结构,它使用索引在数组中搜索和读取数据是很快的。Array获取数据的时间复杂度是O(1),但是要删除数据却是开销很大的,因为这需要重排数组中的所有数据。
  • 相对于ArrayList,LinkedList插入是更快的。因为LinkedList不像ArrayList一样,不需要改变数组的大小,也不需要在数组装满的时候要将所有的数据重新装入一个新的数组,这是ArrayList最坏的一种情况,时间复杂度是O(n),而LinkedList中插入或删除的时间复杂度仅为O(1)。ArrayList在插入数据时还需要更新索引(除了插入数组的尾部)。
  • 类似于插入数据,删除数据时,LinkedList也优于ArrayList。
  • LinkedList需要更多的内存,因为ArrayList的每个索引的位置是实际的数据,而LinkedList中的每个节点中存储的是实际的数据和前后节点的位置。
    在LinkedList中有一个私有的内部类,定义如下:
private static class Entry { 
         Object element; 
         Entry next; 
         Entry previous; 
     } 

这也就是LinkedList耗费内存更多的地方。

什么场景下更适宜使用LinkedList,而不用ArrayList

  • 你的应用不会随机访问数据。因为如果你需要LinkedList中的第n个元素的时候,你需要从第一个元素顺序数到第n个数据,然后读取数据。
  • 你的应用更多的插入和删除元素,更少的读取数据。因为插入和删除元素不涉及重排数据,所以它要比ArrayList要快。

以上就是关于ArrayList和LinkedList的差别。你需要一个不同步的基于索引的数据访问时,请尽量使用ArrayList。ArrayList很快,也很容易使用。但是要记得要给定一个合适的初始大小,尽可能的减少更改数组的大小。

由此可见,LiteGo的使用场景中可能会出现大量的任务插入和删除(插入和删除有可能发生在列表的前面),但并不会涉及到查询,所以这里使用LinkedList是有道理的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容

  • 个人笔记,方便自己查阅使用 Contents Java LangAssignment, ReferenceData...
    freenik阅读 1,376评论 0 6
  • 一.线程安全性 线程安全是建立在对于对象状态访问操作进行管理,特别是对共享的与可变的状态的访问 解释下上面的话: ...
    黄大大吃不胖阅读 836评论 0 3
  • 每天一有空闲时间,我就会阅读微信公众号的推文,查看当天的热点新闻,还会在晚上下班后,把手机调成静音,在家里静静地看...
    柳树之阅读 11,924评论 5 64
  • 1996年,随着一声清脆的哭声,这个小女孩终于来到美好的世界,她瞪着大大的眼睛,看着这陌生的地方,真的好想知道她当...
    二萌小兔阅读 385评论 0 1
  • 朱妍晚上尝了几口土豆后,就把土豆倒了。土豆是甜的,绝对没错。 这是她这周第二次尝到甜的土豆。第一次的时候,她以为是...
    唐小茴阅读 249评论 1 1