(2)Java Executor框架
參考:
Java Executor框架
Executor框架是指java5中引入的一系列并發(fā)庫(kù)中與executor相關(guān)的功能類,包括Executor、Executors、ExecutorService、CompletionService、Future、Callable等。通過學(xué)習(xí)Executor框架能夠更加清楚明晰作者的寫作思路和來源。

開始的開始 Executor
public interface Executor {
void execute(Runnable command);
}
Executor接口是Executor框架中最基礎(chǔ)的部分,定義了一個(gè)用于執(zhí)行Runnable的execute方法。它沒有直接的實(shí)現(xiàn)類,有一個(gè)重要的子接口ExecutorService。
ExecutorService
ExecutorService接口繼承自Executor接口,定義了終止、提交任務(wù)、跟蹤任務(wù)返回結(jié)果等方法。
Runnable、Callable、Future
// 實(shí)現(xiàn)Runnable接口的類將被Thread執(zhí)行,表示一個(gè)基本的任務(wù)
public interface Runnable {
// run方法就是它所有的內(nèi)容,就是實(shí)際執(zhí)行的任務(wù)
public abstract void run();
}
// Callable同樣是任務(wù),與Runnable接口的區(qū)別在于它接收泛型,同時(shí)它執(zhí)行任務(wù)后帶有返回內(nèi)容
public interface Callable<V> {
// 相對(duì)于run方法的帶有返回值的call方法
V call() throws Exception;
}
// Future代表異步任務(wù)的執(zhí)行結(jié)果
public interface Future<V> {
/**
* 嘗試取消一個(gè)任務(wù),如果這個(gè)任務(wù)不能被取消(通常是因?yàn)橐呀?jīng)執(zhí)行完了),返回false,否則返回true。
*/
boolean cancel(boolean mayInterruptIfRunning);
/**
* 返回代表的任務(wù)是否在完成之前被取消了
*/
boolean isCancelled();
/**
* 如果任務(wù)已經(jīng)完成,返回true
*/
boolean isDone();
/**
* 獲取異步任務(wù)的執(zhí)行結(jié)果(如果任務(wù)沒執(zhí)行完將等待)
*/
V get() throws InterruptedException, ExecutionException;
/**
* 獲取異步任務(wù)的執(zhí)行結(jié)果(有最常等待時(shí)間的限制)
*
* timeout表示等待的時(shí)間,unit是它時(shí)間單位
*/
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
ScheduledFuture繼承自Future和Delayed接口,自身沒有添加方法。Delayed接口定義了一個(gè)獲取剩余延遲的方法。
ExecutorService有一個(gè)子接口ScheduledExecutorService和一個(gè)抽象實(shí)現(xiàn)類AbstractExecutorService。
ScheduledExecutorService
可以安排指定時(shí)間或周期性的執(zhí)行任務(wù)的ExecutorService
// 可以安排指定時(shí)間或周期性的執(zhí)行任務(wù)的ExecutorService
public interface ScheduledExecutorService extends ExecutorService {
/**
* 在指定延遲后執(zhí)行一個(gè)任務(wù),只執(zhí)行一次
*/
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
/**
* 與上面的方法相同,只是接受的是Callable任務(wù)
*/
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
/**
* 創(chuàng)建并執(zhí)行一個(gè)周期性的任務(wù),在initialDelay延遲后每間隔period個(gè)單位執(zhí)行一次,時(shí)間單位都是unit
* 每次執(zhí)行任務(wù)的時(shí)間點(diǎn)是initialDelay, initialDelay+period, initialDelay + 2 * period...
*/
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
/**
* 創(chuàng)建并執(zhí)行一個(gè)周期性的任務(wù),在initialDelay延遲后開始執(zhí)行,在執(zhí)行結(jié)束后再延遲delay個(gè)單位開始執(zhí)行下一次任務(wù),時(shí)間單位都是unit
* 每次執(zhí)行任務(wù)的時(shí)間點(diǎn)是initialDelay, initialDelay+(任務(wù)運(yùn)行時(shí)間+delay), initialDelay + 2 * (任務(wù)運(yùn)行時(shí)間+delay)...
*/
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
}
AbstractExecutorService
看到AbstractExecutorService的時(shí)候,基本就能找到一點(diǎn)痕跡了,LiteGo的核心代碼有一些都參照了它的寫法。
我們先來了解下下面三個(gè)概念:
- RunnableFuture繼承自Future和Runnable,只有一個(gè)run()方法。RunnableFuture接口看上去就像是Future和Runnable兩個(gè)接口的組合。
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
- FutureTask類實(shí)現(xiàn)了RunnableFuture接口,除了實(shí)現(xiàn)了Future和Runnable中的方法外,它還有自己的方法。
- ExecutorCompletionService實(shí)現(xiàn)了CompletionService接口,將結(jié)果從復(fù)雜的一部分物種解耦出來。
ThreadPoolExecutor
ThreadPoolExecutor繼承自AbstractExecutorService。
ScheduledThreadPoolExecutor
它繼承自ThreadPoolExecutor并實(shí)現(xiàn)了ScheduledExecutorService接口。
Executors
Executors中所定義的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory
和 Callable
類的工廠和實(shí)用方法。
- newFixedThreadPool
創(chuàng)建一個(gè)定長(zhǎng)的線程池。達(dá)到最大線程數(shù)后,線程數(shù)不再增長(zhǎng)。
如果一個(gè)線程由于非預(yù)期Exception而結(jié)束,線程池會(huì)補(bǔ)充一個(gè)新的線程。 - newCachedThreadPool
創(chuàng)建一個(gè)可緩存的線程池。當(dāng)池長(zhǎng)度超過處理需求時(shí),可以回收空閑的線程。 - newSingleThreadPool
創(chuàng)建一個(gè)單線程executor。 - newScheduledThreadPool
創(chuàng)建一個(gè)定長(zhǎng)的線程池,而且支持定時(shí)的以及周期性的任務(wù)執(zhí)行。
類似于Timer。但是,Timer是基于絕對(duì)時(shí)間,對(duì)系統(tǒng)時(shí)鐘的改變是敏感的,而ScheduledThreadPoolExecutor只支持相對(duì)時(shí)間。
與Timer比較
- Timer是創(chuàng)建唯一的線程來執(zhí)行所有的timer任務(wù)。如果一個(gè)任務(wù)超時(shí)了,會(huì)導(dǎo)致其他的TimerTask時(shí)間準(zhǔn)確性出問題。
- 如果TimerTask拋出uncheck 異常,Timer將會(huì)產(chǎn)生無法預(yù)料的行為。因此,ScheduledThreadPoolExecutor可以完全代替Timer。
(3)LinkedList 和 ArrayList
參考鏈接
因?yàn)槠綍r(shí)我們大多使用的是動(dòng)態(tài)數(shù)組ArrayList,對(duì)LinkedList并不是那么的熟悉,這里探究一下它們的區(qū)別和源碼中為什么要使用LinkedList。
LinkedList和ArrayList都實(shí)現(xiàn)了List接口,但是它們的工作原理卻不一樣。它們之間最主要的區(qū)別在于ArrayList是可改變大小的數(shù)組,而LinkedList是雙向鏈接串列(doubly LinkedList)。
- 因?yàn)锳rray是基于索引(index)的數(shù)據(jù)結(jié)構(gòu),它使用索引在數(shù)組中搜索和讀取數(shù)據(jù)是很快的。Array獲取數(shù)據(jù)的時(shí)間復(fù)雜度是O(1),但是要?jiǎng)h除數(shù)據(jù)卻是開銷很大的,因?yàn)檫@需要重排數(shù)組中的所有數(shù)據(jù)。
- 相對(duì)于ArrayList,LinkedList插入是更快的。因?yàn)長(zhǎng)inkedList不像ArrayList一樣,不需要改變數(shù)組的大小,也不需要在數(shù)組裝滿的時(shí)候要將所有的數(shù)據(jù)重新裝入一個(gè)新的數(shù)組,這是ArrayList最壞的一種情況,時(shí)間復(fù)雜度是O(n),而LinkedList中插入或刪除的時(shí)間復(fù)雜度僅為O(1)。ArrayList在插入數(shù)據(jù)時(shí)還需要更新索引(除了插入數(shù)組的尾部)。
- 類似于插入數(shù)據(jù),刪除數(shù)據(jù)時(shí),LinkedList也優(yōu)于ArrayList。
- LinkedList需要更多的內(nèi)存,因?yàn)锳rrayList的每個(gè)索引的位置是實(shí)際的數(shù)據(jù),而LinkedList中的每個(gè)節(jié)點(diǎn)中存儲(chǔ)的是實(shí)際的數(shù)據(jù)和前后節(jié)點(diǎn)的位置。
在LinkedList中有一個(gè)私有的內(nèi)部類,定義如下:
private static class Entry {
Object element;
Entry next;
Entry previous;
}
這也就是LinkedList耗費(fèi)內(nèi)存更多的地方。
什么場(chǎng)景下更適宜使用LinkedList,而不用ArrayList
- 你的應(yīng)用不會(huì)隨機(jī)訪問數(shù)據(jù)。因?yàn)槿绻阈枰狶inkedList中的第n個(gè)元素的時(shí)候,你需要從第一個(gè)元素順序數(shù)到第n個(gè)數(shù)據(jù),然后讀取數(shù)據(jù)。
- 你的應(yīng)用更多的插入和刪除元素,更少的讀取數(shù)據(jù)。因?yàn)椴迦牒蛣h除元素不涉及重排數(shù)據(jù),所以它要比ArrayList要快。
以上就是關(guān)于ArrayList和LinkedList的差別。你需要一個(gè)不同步的基于索引的數(shù)據(jù)訪問時(shí),請(qǐng)盡量使用ArrayList。ArrayList很快,也很容易使用。但是要記得要給定一個(gè)合適的初始大小,盡可能的減少更改數(shù)組的大小。
由此可見,LiteGo的使用場(chǎng)景中可能會(huì)出現(xiàn)大量的任務(wù)插入和刪除(插入和刪除有可能發(fā)生在列表的前面),但并不會(huì)涉及到查詢,所以這里使用LinkedList是有道理的。