《java併發程式設計的藝術》Executor框架
在HotSport VM執行緒模型中,java執行緒被一對一對映為本地作業系統執行緒。
分兩層:
頂層:Executor框架排程將多執行緒程式分解的若干任務對映為固定數量的執行緒。
底層:作業系統核心將這些執行緒對映到硬體處理器上。
Executor框架結構
- 任務。包括被執行任務需要實現的介面:Runnable介面和Callable介面
- 任務的執行。包括Executor,和ExecutorService介面(ThreadPoolExecutor和ScheduledThreadPoolExecutor)
- 非同步計算的結果。包括介面Future和實現Future介面的FutureTask類
Executor框架的成員
- ThreadPoolExecutor通常由工廠類Executors建立,Executors能建立3中型別的ThreadPoolExecutor。
1)FixedThreadPool。適用於負載比較重的伺服器。有兩個構造方法:
public static ExecutorService newFixedThreadPool(int nThreads)
public static ExecutorService newFixedThreadPool(int nThreads,ThreadFactory threadFactory)
本質上:
new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(),threadFactory);
2)SingleThreadPool。適用於需要保證順序執行各個任務;並且在任意時間點,沒有多執行緒活動的場景。兩個構造方法:
public static ExecutorService newSingleThreadExecutor()
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory)
本質上:
new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));
new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(),threadFactory));
3)CachedThreadPool。大小無界,適用於執行很多的短期非同步任務的小程式,或負載較輕的伺服器。兩個構造方法:
public static ExecutorService newCachedThreadPool()
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory)
本質上:
new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>(),threadFactory)
- ScheduledThreadPoolExecutor extends ThreadPoolExecutor.首先要了解,這個是繼承父類ThreadPoolExecutor的。
public ScheduledThreadPoolExecutor(int corePoolSize,ThreadFactory threadFactory,RejectedExecutionHandler handler) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory, handler);
}
1)ScheduledThreadPool適用於需要多個後臺執行緒執行執行週期任務,同時限制後臺執行緒個數。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)
本質上:
new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue())
new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue(),threadFactory)
2)SingleThreadScheduledExecutor適用於單個執行緒執行週期任務,保證順序。
public static ScheduledExecutorService newSingleThreadScheduledExecutor()
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory)
本質上:
new DelegatedScheduledExecutorService(new ThreadPoolExecutor(1, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue()))
new DelegatedScheduledExecutorService(new ThreadPoolExecutor(1, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue(),threadFactory))
Future介面
Future介面和實現類FutureTask類用來表示非同步計算的結果。當我們呼叫submit方法時返回一個FutureTask物件。注意,在API中能看到返回的是一個實現Future介面的物件,將來可能會對Future實現類進行擴充。Runnable和Callable
Runnable無返回,Callable返回Future。
Executors能把Runnable包裝成Callable:
public static Callable<Object> callable(Runnable task)
public static <T> Callable<T> callable(Runnable task,T result)
ScheduledThreadPoolExecutor
主要用來在給定的延遲之後執行任務,或者定期執行任務。
DelayQueue是一個無界佇列。
執行分兩部分:
1. 當呼叫ScheduledThreadPoolExecute的scheduleAtFixedRate()方法或者scheduleWithFixedDelay()方法時,會向ScheduledThreadPoolExecute的DelayQueue新增一個實現了RunnableScheduleFuture介面的ScheduledFutureTask。
2. 執行緒池中的執行緒從DelayQueue中獲取ScheduledFutureTask,然後執行任務。
ScheduledFutureTask有3個成員變數:
- long型的time,表示這個任務將要被執行的具體時間。
- long型的sequenceNumber,表示這個任務被新增到ScheduledThreadPoolExecutor中的序號
- long型的period,表示任務執行的間隔週期。
DelayQueue封裝了一個PriorityQueue,這個PrioriyQueue會對佇列中的ScheduledFutureTask進行排序。排序時,time小的排在前面,time相同的則比較sequenceNumber,小的排前面。
執行步驟:
1. 從DelayQueue獲取已到期的ScheduleFutureTask(DelayQueue.take())。到期任務是指ScheduledFutureTask的time大於等於當前時間。
2. 執行ScheduledFutureTask
3. 修改ScheduledFutureTask的time為下次將要執行的時間
4. 把修改time後的ScheduledFutureTask放回DelayQueue中(DelayQueue.add())
獲取任務3大步驟:
1. 獲取Lock
2. 獲取週期任務
- 如果佇列為空,當前執行緒到Condition中等待;否則執行下面一點
- 如果佇列的頭元素time時間比當前時間大,則到Condition中等待到time時間,否則執行下一點
- 獲取佇列的頭元素,如果佇列不為空,則喚醒Condition中等待的所有執行緒
3. 釋放Lock
FutureTask
FutureTask除了實現Future介面外,還實現Runnable介面。所以FutureTask可以交給Executor執行,也可以呼叫執行緒直接執行(FutureTask.run()).根據FutureTask.run()方法被執行的時機,FutureTask可以處於下面3種狀態:1. 未啟動 2. 已啟動 3. 已完成(正常完成、FutureTask.cancel()、拋異常結束)
FutureTask的實現基於AQS。每一個基於AQS實現的同步器都會包含兩種型別的操作:
1. 至少一個acquire操作。這個操作阻塞呼叫執行緒,除非/直到AQS的狀態允許這個執行緒執行。FutureTask中為get()/get(long timeout,TimeUnit unit)方法呼叫。
2. 至少一個release操作。這個操作改變AQS的狀態,改變後的狀態可允許一個或多個阻塞執行緒被解除阻塞。FutureTask中為run方法和cancel方法。
相關文章
- Java 併發程式設計 Executor 框架Java程式設計框架
- 《java併發程式設計的藝術》併發容器和框架Java程式設計框架
- Java併發程式設計藝術Java程式設計
- 《java併發程式設計的藝術》併發工具類Java程式設計
- Java併發程式設計的藝術,解讀併發程式設計的優缺點Java程式設計
- 《java併發程式設計的藝術》原子操作類Java程式設計
- Java併發程式設計的藝術(五)——中斷Java程式設計
- 《java併發程式設計的藝術》併發底層實現原理Java程式設計
- 《java併發程式設計的藝術》記憶體模型Java程式設計記憶體模型
- 《java併發程式設計的藝術》執行緒池Java程式設計執行緒
- 【讀書筆記】Java併發程式設計的藝術筆記Java程式設計
- Java核心技術學習筆記——進階——第五章 Java多執行緒和併發程式設計——5.5 Java併發框架ExecutorJava筆記執行緒程式設計框架
- 如何評價《Java 併發程式設計藝術》這本書?Java程式設計
- Java併發程式設計之Executor執行緒池原理與原始碼解讀Java程式設計執行緒原始碼
- java併發程式設計系列:java併發程式設計背景知識Java程式設計
- 【Java併發程式設計的藝術】第二章讀書筆記之原子操作Java程式設計筆記
- java 併發程式設計Java程式設計
- Java併發程式設計Java程式設計
- Java併發程式設計---java規範與模式下的併發程式設計1.1Java程式設計模式
- Java併發程式設計 - 第十一章 Java併發程式設計實踐Java程式設計
- Java併發程式設計藝術第二章-----第二遍讀後記錄Java程式設計
- Java併發程式設計—ThreadLocalJava程式設計thread
- Java併發程式設計:synchronizedJava程式設計synchronized
- Java併發程式設計 -- ThreadLocalJava程式設計thread
- Java併發程式設計 -- ConditionJava程式設計
- Java併發程式設計——ThreadLocalJava程式設計thread
- java-併發程式設計Java程式設計
- Java 併發程式設計解析Java程式設計
- Java併發程式設計-CASJava程式設計
- Java併發程式設計:LockJava程式設計
- Java併發程式設計ForkJoin的DemoJava程式設計
- Java併發程式設計-鎖及併發容器Java程式設計
- 深入理解併發程式設計藝術之計算機記憶體模型程式設計計算機記憶體模型
- Java併發程式設計(07):Fork/Join框架機制詳解Java程式設計框架
- Java併發程式設計之synchronizedJava程式設計synchronized
- Java併發程式設計實踐Java程式設計
- Java併發程式設計基礎Java程式設計
- Java 併發程式設計要點Java程式設計