-
1 # raning1
-
2 # 碼農二胖
我們可以先看下執行緒池的類圖
我們可以透過java.util.concurrent.ThreadPoolExecutor來建立一個執行緒池。
執行緒池的核心引數如下,這也是常問的面試題。
corePoolSize(執行緒池的基本大小):當提交一個任務到執行緒池時,執行緒池會建立一個執行緒來執行任務,即使其他空閒的基本執行緒能夠執行新任務也會建立執行緒,等到需要執行的任務數大於執行緒池基本大小時就不再建立。如果呼叫了執行緒池的prestartAllCoreThreads方法,執行緒池會提前建立並啟動所有基本執行緒。
runnableTaskQueue(任務佇列):用於儲存等待執行的任務的阻塞佇列。 可以選擇以下幾個阻塞佇列。
ArrayBlockingQueue:是一個基於陣列結構的有界阻塞佇列,此佇列按 FIFO(先進先出)原則對元素進行排序。
LinkedBlockingQueue:一個基於連結串列結構的阻塞佇列,此佇列按FIFO (先進先出) 排序元素,吞吐量通常要高於ArrayBlockingQueue。靜態工廠方法Executors.newFixedThreadPool()使用了這個佇列。
SynchronousQueue:一個不儲存元素的阻塞佇列。每個插入操作必須等到另一個執行緒呼叫移除操作,否則插入操作一直處於阻塞狀態,吞吐量通常要高於LinkedBlockingQueue,靜態工廠方法Executors.newCachedThreadPool使用了這個佇列。
PriorityBlockingQueue:一個具有優先順序的無限阻塞佇列。
maximumPoolSize(執行緒池最大大小):執行緒池允許建立的最大執行緒數。如果佇列滿了,並且已建立的執行緒數小於最大執行緒數,則執行緒池會再建立新的執行緒執行任務。值得注意的是如果使用了無界的任務佇列這個引數就沒什麼效果。
ThreadFactory:用於設定建立執行緒的工廠,可以透過執行緒工廠給每個創建出來的執行緒設定更有意義的名字。
RejectedExecutionHandler(飽和策略):當佇列和執行緒池都滿了,說明執行緒池處於飽和狀態,那麼必須採取一種策略處理提交的新任務。這個策略預設情況下是AbortPolicy,表示無法處理新任務時丟擲異常。以下是JDK1.5提供的四種策略。
AbortPolicy:直接丟擲異常。
CallerRunsPolicy:只用呼叫者所線上程來執行任務。
DiscardOldestPolicy:丟棄佇列裡最近的一個任務,並執行當前任務。
DiscardPolicy:不處理,丟棄掉。
當然也可以根據應用場景需要來實現RejectedExecutionHandler介面自定義策略。如記錄日誌或持久化不能處理的任務。
keepAliveTime(執行緒活動保持時間):執行緒池的工作執行緒空閒後,保持存活的時間。所以如果任務很多,並且每個任務執行的時間比較短,可以調大這個時間,提高執行緒的利用率。
TimeUnit(執行緒活動保持時間的單位):可選的單位有天(DAYS),小時(HOURS),分鐘(MINUTES),毫秒(MILLISECONDS),微秒(MICROSECONDS, 千分之一毫秒)和毫微秒(NANOSECONDS, 千分之一微秒)。
還有一個面試題經常也會被問到
核心執行緒數和最大執行緒數是怎麼一個關係?
核心執行緒滿了,接下來進佇列,佇列也滿了,建立新執行緒,直到達到最大執行緒數,之後再超出,會進入拒絕rejectedExecution。
回覆列表
提交任務後,執行緒池先判斷執行緒數是否達到了核心執行緒數(corePoolSize)。如果未達到執行緒數,則建立核心執行緒處理任務;否則,就執行下一步;
接著執行緒池判斷任務佇列是否滿了。如果沒滿,則將任務新增到任務佇列中;否則,執行下一步;
接著因為任務佇列滿了,執行緒池就判斷執行緒數是否達到了最大執行緒數。如果未達到,則建立非核心執行緒處理任務;否則,就執行飽和策略,預設會丟擲RejectedExecutionException異常。