leetcode刷題筆記 235題 二叉搜尋樹的最近公共祖先
1.Java常見的四種執行緒池
1.1 newFixedThreadPool(int poolSize)
建立一個大小為poolSize的固定執行緒池,執行緒池是無邊界阻塞佇列。程式碼如下
ExecutorService exec = Executors.newFixedThreadPool(poolSize);
//它實際上是建立了一個ThreadPoolExecutor例項
new
ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,
new
LinkedBlockingQueue<Runnable>());
//第一個引數是核心執行緒數;第二個引數是最大執行緒數;0L是長整型,代表當執行緒數量大於核心數時,在終止前,額外執行緒等待新任務的最大時間;第四個引數代表第三個引數的時間單位,這裡是毫秒,第五個引數代表建立一個無邊界的佇列。
1.2 newSingleThreadExecutor()
建立一個單執行緒池,類似於newFixedThreadPool(1)ExecutorService exec = Executors.newSingleThreadExecutor();
//它建立了一個被FinalizableDelegatedExecutorService修飾的ThreadPoolExecutor例項,所以它只有ThreadPoolExecutor的部分功能,且會被GC回收
new
FinalizableDelegatedExecutorService(
new
ThreadPoolExecutor(
1
,
1
, 0L, TimeUnit.MILLISECONDS,
new
LinkedBlockingQueue<Runnable>()));
1.3 newCachedThreadPool()
建立一個具有緩衝功能的執行緒池
ExecutorService exec = Executors.newCachedThreadPool();
//它建立了ThreadPoolExecutor例項,它是一個同步佇列
new
ThreadPoolExecutor(
0
, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
new
SynchronousQueue<Runnable>());
//這會建立一個無界的執行緒池,執行緒可以空閒的最大時間是60秒,在這60秒都是已建立的執行緒都是可以複用的。
1.4 newScheduledThreadPool(int poolSize)
建立一個具有計劃執行的固定大小執行緒池
ExecutorService exec = Executors.newScheduledThreadPool(poolSize)
//它建立了ThreadPoolExecutor例項,但是使用的是優先順序佇列
new
ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE,
0
, NANOSECONDS,
new
DelayedWorkQueue())
2.ThreadPoolExecutor
由於使用上面的執行緒池或多或少有些限制,所以使用底層的ThreadPoolExecutor可以自定義執行緒池的屬性。
2.1 引數詳解
第一個引數corePoolSize意思是核心執行緒大小;執行緒池中保留的執行緒數,即使是空閒狀態也保留,除非設定了允許核心執行緒超時,預設是不設定,即不銷燬核心執行緒
第二個引數是最大執行緒數;
第三個是keepAliveTime保留時間,當最大執行緒數大於核心執行緒數時,多餘的執行緒保留時間,超過這個時間多餘的執行緒將被銷燬。
第四個是第三個時間的時間單位,是屬於TimeUnit的列舉值。
第五個是一個阻塞佇列,在任務提交執行前,任務都是這個阻塞佇列的內容。
第六個是執行緒工廠,這種工廠模式會被用於建立新執行緒。
第七個是拒絕策略,當執行緒池執行緒達到最大值,阻塞佇列排滿時使用這個引數,,預設是拋棄執行超出的任務,直接拋異常。
2.2 阻塞佇列
2.2.1 ArrayBlockingQueue
基於陣列的有界阻塞佇列,規則是FIFO(先進先出)。
2.2.2 LinkedBlockingQUeue
基於連結串列的無界阻塞佇列,規則也是FIFO,如果不設定大小,預設是無界的,此時可能會造成記憶體溢位等問題。
2.2.3 SychronousQueue
同步的阻塞佇列,它不儲存元素,上一個元素執行完才能執行下一個元素。
2.3 拒絕策略
ThreadPoolExecutor類有4個拒絕策略的內部類。預設的拒絕策略是AbortPolicy。
2.3.1 AbortPolicy
執行緒池達到最大執行緒數且阻塞佇列滿,直接丟擲異常
2.3.2 DiscardPolicy
執行緒池達到最大執行緒數且阻塞佇列滿,遺棄這個任務
2.3.3 DiscardOldestPolicy
執行緒池達到最大執行緒數且阻塞佇列滿,遺棄最舊的任務,嘗試將新任務新增到新執行緒池
2.3.4 CallerRunPolicy
執行緒池達到最大執行緒數且阻塞佇列滿,嘗試使用主執行緒執行該任務
2.4 執行緒池工作原理
2.4.1 原理
第一步,執行緒池判斷核心執行緒池是否都在執行任務,若不是,則建立執行緒來執行任務;若是,則執行第二步
第二步,使用阻塞佇列來儲存任務,若阻塞佇列已滿,則執行第三步。
第三步,執行緒池判斷現在是否達到最大執行緒數,若不是,建立執行緒來執行任務,若是,則執行飽和策略。