使用Java?Executors創(chuàng)建線程池的9種方法
在 Java 中,Executors
類提供了多種靜態(tài)工廠方法來創(chuàng)建不同類型的線程池。學習線程池時,Executors
類不可或缺。掌握其用法、原理和適用場景,有助于在實際項目開發(fā)中順利應用。以下是一些常用方法,我將逐一解釋:
newCachedThreadPool()
:創(chuàng)建一個可緩存線程池。如果一個線程 60 秒未被使用,將被終止并從緩存中移除。newFixedThreadPool(int nThreads)
:創(chuàng)建一個固定大小的線程池,其中nThreads
指定池中的線程數(shù)量。newSingleThreadExecutor()
:創(chuàng)建一個單線程執(zhí)行器,創(chuàng)建單個工作線程來執(zhí)行任務。newScheduledThreadPool(int corePoolSize)
:創(chuàng)建一個固定大小的線程池,可根據(jù)需要創(chuàng)建新線程,但會按照給定的初始延遲執(zhí)行任務。newWorkStealingPool(int parallelism)
:創(chuàng)建一個工作竊取線程池,使用多個隊列,每個線程從自己的隊列中竊取任務。newSingleThreadScheduledExecutor()
:創(chuàng)建一個單線程調度執(zhí)行器,可根據(jù)需要創(chuàng)建新線程來執(zhí)行任務。privilegedThreadFactory()
:創(chuàng)建一個線程工廠,用于創(chuàng)建具有特權訪問權限的線程。defaultThreadFactory()
:創(chuàng)建一個默認線程工廠,用于創(chuàng)建沒有特殊權限的標準線程。unconfigurableExecutorService(ExecutorService executor)
:將給定的ExecutorService
轉換為不可配置版本,使調用者無法修改其配置。
這些方法提供了靈活的方式來創(chuàng)建和管理線程池,以滿足不同的并發(fā)需求。下面,我將詳細介紹這 9 種方法的實現(xiàn)和使用場景。
newCachedThreadPool()
newCachedThreadPool
方法是 Java java.util.concurrent
包中Executors
類的靜態(tài)工廠方法。此方法創(chuàng)建一個可緩存線程池,可根據(jù)需要動態(tài)創(chuàng)建新線程,并終止在一定時間內未使用的空閑線程。
實現(xiàn)原理
- 線程創(chuàng)建:當向線程池提交任務時,如果當前線程數(shù)小于核心池大小,將創(chuàng)建新線程。
- 線程重用:如果當前線程數(shù)等于核心池大小,新任務將被放入任務隊列等待執(zhí)行。
- 線程終止:空閑線程在指定時間(默認為 60 秒)內未被使用將被終止,以減少資源消耗。
源代碼分析
在 Java 的java.util.concurrent
包中,Executors
類并不直接提供newCachedThreadPool
的實現(xiàn)。相反,它使用ThreadPoolExecutor
構造函數(shù)。以下是ThreadPoolExecutor
調用的示例:
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue()); }
參數(shù)解釋
corePoolSize
:核心線程數(shù),這里設置為 0,表示線程池不保留任何核心線程。maximumPoolSize
:最大線程數(shù),設置為Integer.MAX_VALUE
,理論上允許無限數(shù)量的線程。keepAliveTime
:多余空閑線程在終止前等待新任務的最長時間,這里設置為 60 秒。unit
:keepAliveTime
參數(shù)的時間單位,這里是秒。workQueue
:任務隊列。這里使用SynchronousQueue
,這是一個不存儲元素的阻塞隊列,要求每個插入操作都等待相應的移除操作。
實現(xiàn)過程
- 初始化:調用
newCachedThreadPool
時,創(chuàng)建一個ThreadPoolExecutor
實例。 - 任務提交:向線程池提交任務時,池檢查是否有空閑線程可用于執(zhí)行任務。
- 線程創(chuàng)建:如果沒有空閑線程且當前線程數(shù)小于
maximumPoolSize
,則創(chuàng)建新線程來執(zhí)行任務。 - 任務隊列:如果當前線程數(shù)已達到
maximumPoolSize
,任務將被放入SynchronousQueue
等待執(zhí)行。 - 線程重用:線程完成任務后,不會立即終止,而是嘗試從
SynchronousQueue
獲取新任務。 - 線程終止:如果線程在
keepAliveTime
內未收到新任務,將終止。
這種設計使newCachedThreadPool
非常適合處理大量短期異步任務,因為它可以動態(tài)調整線程數(shù)量以適應不同的工作負載。然而,由于它可以創(chuàng)建無限數(shù)量的線程,因此必須考慮任務的特性和系統(tǒng)資源限制,以防止資源耗盡。
使用場景
適用于執(zhí)行許多短期異步任務,特別是當任務的執(zhí)行時間不確定時。例如,處理 Web 服務器上的大量并發(fā)請求或異步日志記錄。
newFixedThreadPool(int nThreads)
newFixedThreadPool(int nThreads)
方法是 Java java.util.concurrent
包中Executors
類的靜態(tài)工廠方法。此方法創(chuàng)建一個具有固定線程數(shù)的線程池,確保池中的線程數(shù)量保持不變。
實現(xiàn)原理
- 固定線程數(shù):線程池中的線程數(shù)量始終保持為
nThreads
。 - 任務隊列:提交到池中的任務首先由核心線程執(zhí)行。如果所有核心線程都忙碌,新任務將被放入阻塞隊列等待執(zhí)行。
- 線程重用:池中的線程會被重用;完成一個任務后,線程將立即嘗試從隊列中獲取下一個任務執(zhí)行。
源代碼分析
newFixedThreadPool
方法通過調用ThreadPoolExecutor
類的構造函數(shù)來實現(xiàn)。以下是ThreadPoolExecutor
調用的示例:
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor( nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue() ); }
參數(shù)解釋
corePoolSize
:核心線程數(shù),設置為nThreads
,表示池始終有nThreads
個線程。maximumPoolSize
:最大線程數(shù),也設置為nThreads
,確保池大小不超過nThreads
。keepAliveTime
:多余空閑線程在終止前等待新任務的最長時間,這里設置為 0,表示任何超過核心池大小的線程將立即終止。unit
:keepAliveTime
參數(shù)的時間單位,這里是毫秒。workQueue
:任務隊列。這里使用LinkedBlockingQueue
,這是一個基于鏈表的阻塞隊列,可以存儲任意數(shù)量的任務。
實現(xiàn)過程
- 初始化:調用
newFixedThreadPool
時,創(chuàng)建一個ThreadPoolExecutor
實例。 - 任務提交:向池提交任務時,檢查是否有空閑核心線程可立即執(zhí)行任務。
- 任務隊列:如果所有核心線程都忙碌,新任務將被放入
LinkedBlockingQueue
等待執(zhí)行。 - 線程重用:核心線程完成任務后,將嘗試從
LinkedBlockingQueue
獲取新任務繼續(xù)執(zhí)行。 - 線程數(shù)控制:由于
keepAliveTime
設置為 0,任何超過核心池大小的線程將立即終止,確保池中的線程數(shù)量不超過nThreads
。
這種設計使newFixedThreadPool
非常適合處理大量穩(wěn)定的任務流,因為它確保任務由固定數(shù)量的線程并行執(zhí)行,避免線程不受控制地增長。然而,由于池大小是固定的,如果任務提交速率超過池的處理能力,任務可能會在隊列中長時間等待。因此,使用newFixedThreadPool
時,根據(jù)任務的特性和預期工作負載設置nThreads
非常重要。
使用場景
適用于執(zhí)行大量長時間運行的任務,且需要固定線程數(shù)量的情況。例如,同時運行多個數(shù)據(jù)加載或數(shù)據(jù)處理任務,同時限制并發(fā)以避免資源過載。
newSingleThreadExecutor()
newSingleThreadExecutor
方法是 Java java.util.concurrent
包中Executors
類的靜態(tài)工廠方法。此方法創(chuàng)建一個單線程執(zhí)行器,確保所有任務按提交順序依次執(zhí)行,使用單個線程。
實現(xiàn)原理
- 單線程執(zhí)行:線程池只包含一個線程,確保所有任務由這個單線程按順序執(zhí)行。
- 任務隊列:如果在單線程忙碌時提交新任務,任務將被放入阻塞隊列等待執(zhí)行。
- 線程重用:單線程會被重用;完成一個任務后,它將立即嘗試從隊列中獲取下一個任務執(zhí)行。
源代碼分析
newSingleThreadExecutor
方法通過調用ThreadPoolExecutor
類的構造函數(shù)來實現(xiàn)。以下是ThreadPoolExecutor
調用的示例:
public static ExecutorService newSingleThreadExecutor() { return new ThreadPoolExecutor( 1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue() ); }
參數(shù)解釋
corePoolSize
:核心線程數(shù),設置為 1,表示池始終有一個核心線程。maximumPoolSize
:最大線程數(shù),也設置為 1,確保池大小不超過一個線程。keepAliveTime
:多余空閑線程在終止前等待新任務的最長時間,這里設置為 0,表示線程空閑時將立即終止。unit
:keepAliveTime
參數(shù)的時間單位,這里是毫秒。workQueue
:任務隊列。這里使用LinkedBlockingQueue
,這是一個可以存儲任意數(shù)量任務的阻塞隊列。
實現(xiàn)過程
- 初始化:調用
newSingleThreadExecutor
時,創(chuàng)建一個ThreadPoolExecutor
實例。 - 任務提交:向池提交任務時,如果核心線程空閑,它將立即執(zhí)行任務;如果核心線程忙碌,任務將被放入
LinkedBlockingQueue
等待。 - 順序執(zhí)行:由于只有一個線程,所有任務按提交順序執(zhí)行。
- 任務隊列:如果核心線程正在執(zhí)行任務,新任務將被放入
LinkedBlockingQueue
等待。 - 線程重用:核心線程完成任務后,將嘗試從
LinkedBlockingQueue
獲取新任務繼續(xù)執(zhí)行。 - 線程數(shù)控制:由于
keepAliveTime
設置為 0,核心線程在沒有任務可執(zhí)行時將立即終止。然而,因為corePoolSize
和maximumPoolSize
都為 1,線程池將立即重新創(chuàng)建一個新線程。
這種設計使newSingleThreadExecutor
非常適合需要保證任務順序執(zhí)行的場景,例如任務有依賴關系或必須按特定順序執(zhí)行的情況。此外,由于只有一個線程,它避免了多線程環(huán)境中固有的并發(fā)問題。然而,單線程執(zhí)行也限制了并行處理能力;如果一個任務執(zhí)行時間較長,后續(xù)任務可能會經歷顯著的延遲。因此,使用newSingleThreadExecutor
時,考慮任務的性質和順序執(zhí)行的要求非常重要。
使用場景
- 保證順序執(zhí)行:適用于需要任務按特定順序執(zhí)行的場景,例如隊列中消息或事件的順序處理。
- 單后臺線程執(zhí)行定期任務:適用于需要單個后臺線程持續(xù)處理定期任務的情況。
通過使用newSingleThreadExecutor
,開發(fā)人員可以確保任務按提交順序執(zhí)行,而無需管理多個線程的復雜性和潛在問題。
newScheduledThreadPool(int corePoolSize)
newScheduledThreadPool
方法是 Java java.util.concurrent
包中Executors
類的靜態(tài)工廠方法。此方法用于創(chuàng)建一個固定大小的線程池,支持執(zhí)行定時和周期性任務。
實現(xiàn)原理
- 定時任務:線程池可以執(zhí)行具有指定延遲或固定間隔的任務。
- 固定線程數(shù):池中的線程數(shù)量限制為
corePoolSize
指定的大小。 - 任務隊列:任務首先由核心線程執(zhí)行。如果所有核心線程都忙碌,新任務將被放入延遲隊列等待執(zhí)行。
源代碼分析
newScheduledThreadPool
方法通過調用ScheduledThreadPoolExecutor
類的構造函數(shù)來實現(xiàn)。以下是調用示例:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
ScheduledThreadPoolExecutor
是ThreadPoolExecutor
的子類,專門用于執(zhí)行定時任務。ScheduledThreadPoolExecutor
構造函數(shù)的corePoolSize
參數(shù)定義了池中核心線程的數(shù)量。
內部,ScheduledThreadPoolExecutor
使用DelayedWorkQueue
作為其任務隊列,該隊列根據(jù)任務的預定執(zhí)行時間對任務進行排序。
實現(xiàn)過程
- 初始化:調用
newScheduledThreadPool
時,創(chuàng)建一個ScheduledThreadPoolExecutor
實例。 - 任務提交:向池提交任務時,根據(jù)其預定執(zhí)行時間將其放入
DelayedWorkQueue
。 - 任務調度:池中的線程從
DelayedWorkQueue
中獲取任務,并在預定時間到達時執(zhí)行它們。 - 線程重用:完成任務的線程將嘗試從
DelayedWorkQueue
獲取下一個任務。 - 線程數(shù)控制:如果任務數(shù)量超過核心線程的處理能力,
ScheduledThreadPoolExecutor
將創(chuàng)建新線程來幫助處理任務,最多達到corePoolSize
定義的限制。
特性
- 線程工廠:
ScheduledThreadPoolExecutor
允許設置線程工廠來創(chuàng)建具有特定屬性的線程。 - 拒絕執(zhí)行處理程序:它允許設置
RejectedExecutionHandler
來處理無法接受的任務(例如,當池關閉或任務隊列已滿時)。 - 關閉行為:與
ThreadPoolExecutor
不同,ScheduledThreadPoolExecutor
的shutdown
和shutdownNow
方法不會等待延遲任務完成。
newScheduledThreadPool
方法非常適合需要執(zhí)行定時任務的場景,例如周期性后臺任務或計劃在特定時間運行的任務。然而,由于它基于固定大小的線程池,在高負載下,任務可能會排隊等待執(zhí)行。因此,在設計時考慮適當?shù)?code>corePoolSize以滿足性能要求非常重要。
使用場景
- 周期性任務執(zhí)行:適用于需要定期執(zhí)行任務的場景,例如定期數(shù)據(jù)備份或周期性狀態(tài)檢查。
- 延遲任務執(zhí)行:適用于需要在未來某個時間點執(zhí)行的任務,例如發(fā)送提醒或計劃更新。
通過使用newScheduledThreadPool
,開發(fā)人員可以有效地管理和調度需要在固定間隔或特定時間執(zhí)行的任務,確保任務由固定數(shù)量的線程正確處理。
newWorkStealingPool(int parallelism)
newWorkStealingPool(int parallelism)
方法是 Java 8 中引入的java.util.concurrent
包中Executors
類的靜態(tài)工廠方法。此方法創(chuàng)建一個工作竊取線程池,可提高并行任務的執(zhí)行效率,特別是在多處理器系統(tǒng)上。
實現(xiàn)原理
- 工作竊取:在工作竊取線程池中,每個線程都有自己的任務隊列。當一個線程完成其任務時,它會嘗試從其他線程的隊列中“竊取”任務。
- 并行級別:線程池的大小由
parallelism
參數(shù)確定,通常等于主機上的處理器核心數(shù)量。 - 動態(tài)調整:工作竊取線程池可以動態(tài)添加或刪除線程,以適應任務負載和線程利用率。
源代碼分析
newWorkStealingPool
方法通過調用ForkJoinPool
類的靜態(tài)工廠方法來實現(xiàn)。以下是調用示例:
public static ExecutorService newWorkStealingPool(int parallelism) { return new ForkJoinPool( parallelism, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, false ); }
參數(shù)解釋
parallelism
:并行級別,即線程池中的線程數(shù)量。ForkJoinPool.defaultForkJoinWorkerThreadFactory
:用于創(chuàng)建線程的默認線程工廠。null
:未捕獲異常處理程序,這里未指定,因此如果任務拋出未捕獲異常,它將傳播到ForkJoinTask
的調用者。false
:表示這不是異步任務。
ForkJoinPool
內部使用ForkJoinWorkerThread
來執(zhí)行任務,每個線程都有一個ForkJoinQueue
來存儲任務。
實現(xiàn)過程
- 初始化:調用
newWorkStealingPool
時,創(chuàng)建一個ForkJoinPool
實例。 - 任務提交:向池提交任務時,任務被放入調用線程的本地隊列。
- 任務執(zhí)行:每個線程首先嘗試從其本地隊列執(zhí)行任務。
- 工作竊取:如果本地隊列為空,線程嘗試從其他線程的隊列中竊取任務。
- 動態(tài)調整:線程池可以根據(jù)需要動態(tài)添加或刪除線程。
特性
- 工作竊取:這種機制特別適合工作負載不均勻分布的情況,因為它減少了空閑時間并提高了資源利用率。
- 并行計算:適合可以分解為多個子任務的并行計算任務,因為任務可以被分割并將子任務提交到線程池。
- 減少競爭:由于每個線程都有自己的隊列,鎖競爭減少,提高了并發(fā)性能。
newWorkStealingPool
非常適合需要高并發(fā)和高吞吐量的場景,特別是在多處理器系統(tǒng)上。然而,由于工作竊取機制,它可能不適合任務執(zhí)行時間非常短或任務數(shù)量非常少的場景,因為竊取本身可能會引入額外的開銷。
使用場景
- 不均勻工作負載:適用于工作負載不均勻或可以分解為多個較小任務的任務,如圖像處理或數(shù)據(jù)分析。
- 多核處理器利用:有效利用多核處理器的所有核心。
通過使用newWorkStealingPool
,開發(fā)人員可以有效地管理和執(zhí)行并行任務,充分利用多核處理器的能力并提高并發(fā)應用程序的性能。
newSingleThreadScheduledExecutor()
newSingleThreadScheduledExecutor
是 Java java.util.concurrent
包中Executors
類的靜態(tài)工廠方法。此方法創(chuàng)建一個單線程調度執(zhí)行器,可調度命令在給定延遲后運行或定期執(zhí)行。
實現(xiàn)原理
- 單線程執(zhí)行:執(zhí)行器確保所有任務在單個線程中按順序執(zhí)行,維護任務執(zhí)行順序。
- 定時任務:支持延遲和定期任務執(zhí)行。
- 任務隊列:所有任務首先被放入任務隊列,然后由單個線程按順序執(zhí)行。
源代碼分析
newSingleThreadScheduledExecutor
方法通過調用ScheduledThreadPoolExecutor
類的構造函數(shù)來實現(xiàn)。以下是調用示例:
public static ScheduledExecutorService newSingleThreadScheduledExecutor() { return new ScheduledThreadPoolExecutor(1); }
這里,ScheduledThreadPoolExecutor
是ExecutorService
的一個實現(xiàn),專門用于執(zhí)行定時任務。構造函數(shù)有一個參數(shù),即核心池大小。將其設置為 1 表示這是一個單線程執(zhí)行器。
ScheduledThreadPoolExecutor
內部使用DelayedWorkQueue
作為任務隊列。此隊列可以根據(jù)任務的預定執(zhí)行時間對任務進行排序。
實現(xiàn)過程
- 初始化:調用
newSingleThreadScheduledExecutor
時,創(chuàng)建一個核心池大小為 1 的ScheduledThreadPoolExecutor
實例。 - 任務提交:向執(zhí)行器提交任務時,它被包裝成
ScheduledFutureTask
或RunnableScheduledFuture
并放入DelayedWorkQueue
。 - 任務調度:單線程不斷從
DelayedWorkQueue
獲取任務,并在預定時間執(zhí)行它們。如果執(zhí)行時間已到,任務將被執(zhí)行;如果未到,線程將等待直到執(zhí)行時間到達。 - 順序執(zhí)行:由于只有一個線程,所有任務按提交順序執(zhí)行。
- 定期任務:對于需要定期執(zhí)行的任務,執(zhí)行器在每次執(zhí)行后重新計算下一次執(zhí)行時間,并將任務放回隊列。
特性
- 順序維護:
newSingleThreadScheduledExecutor
非常適合需要維護任務順序的場景,例如任務有依賴關系或特定順序的情況。 - 并發(fā)簡化:只有一個線程避免了并發(fā)問題,簡化了任務同步和狀態(tài)管理。
- 定時執(zhí)行:它為任務提供了強大的調度功能,例如定期維護或后臺任務。
使用場景
- 順序任務執(zhí)行:適用于任務需要按特定順序執(zhí)行或有依賴關系的場景。
- 定時后臺任務:適用于需要定期執(zhí)行的任務,例如定期系統(tǒng)檢查或維護任務。
privilegedThreadFactory()
privilegedThreadFactory
是 Java java.util.concurrent
包中Executors
類的靜態(tài)工廠方法。此方法創(chuàng)建一個線程工廠,生成具有特權訪問權限的線程。這些線程可以訪問系統(tǒng)屬性、加載系統(tǒng)庫和訪問文件系統(tǒng)。
實現(xiàn)原理
- 特權訪問:此工廠創(chuàng)建的線程有權訪問系統(tǒng)資源,如加載系統(tǒng)屬性和庫。
- 線程創(chuàng)建:線程工廠創(chuàng)建新的線程實例,這些實例繼承創(chuàng)建它們的線程的上下文。
源代碼分析
privilegedThreadFactory
方法的實現(xiàn)細節(jié)在標準 Java 庫中未公開暴露。然而,我們可以通過檢查其一般工作方式來理解其功能。以下是privilegedThreadFactory
方法可能的調用示例:
public static ThreadFactory privilegedThreadFactory() { return new PrivilegedThreadFactory(); }
這里,PrivilegedThreadFactory
是Executors
類中的私有靜態(tài)內部類,實現(xiàn)了ThreadFactory
接口。ThreadFactory
接口定義了newThread(Runnable r)
方法用于創(chuàng)建新線程。
實現(xiàn)過程
- 初始化:調用
privilegedThreadFactory
方法時,返回一個新的PrivilegedThreadFactory
實例。 - 線程創(chuàng)建:當使用此工廠創(chuàng)建線程時,它調用
newThread(Runnable r)
方法。 - 特權訪問:在
newThread(Runnable r)
方法實現(xiàn)中,使用AccessController.doPrivileged
方法確保新創(chuàng)建的線程具有特權訪問權限。 - 上下文繼承:新線程通常繼承創(chuàng)建它的線程的上下文,包括類加載器和其他設置。
示例
雖然我們無法查看privilegedThreadFactory
的精確實現(xiàn),但我們可以提供一個示例實現(xiàn)來演示如何創(chuàng)建特權線程:
public class PrivilegedThreadFactory implements ThreadFactory { @Override public Thread newThread(Runnable r) { return AccessController.doPrivileged(new PrivilegedAction<>() { @Override public Thread run() { return new Thread(r); } }); } }
在這個示例中,PrivilegedAction
是一個實現(xiàn)PrivilegedAction
接口的匿名類,其中run
方法創(chuàng)建一個新線程。AccessController.doPrivileged
方法執(zhí)行一個特權操作,以確保線程創(chuàng)建過程具有必要的權限。
特性
- 特權訪問:使用
privilegedThreadFactory
創(chuàng)建的線程可以訪問敏感系統(tǒng)資源,適用于需要此類訪問的應用程序。 - 簡化安全:使用
AccessController.doPrivileged
確保線程在執(zhí)行期間被授予適當?shù)陌踩珯嘞蕖?/li> - 上下文繼承:新線程繼承其父線程的上下文,包括類加載器和其他安全設置。
使用場景
- 訪問系統(tǒng)資源:適用于需要線程具有更高權限以訪問系統(tǒng)屬性或執(zhí)行文件 I/O 操作的應用程序。
- 安全敏感操作:確保執(zhí)行安全敏感操作的線程具有必要的權限,以避免安全異常。
defaultThreadFactory()
defaultThreadFactory
是 Java java.util.concurrent
包中Executors
類的靜態(tài)工廠方法。此方法創(chuàng)建一個默認線程工廠,生成具有標準屬性的線程,沒有特殊權限。
實現(xiàn)原理
- 標準線程創(chuàng)建:線程工廠生成具有默認屬性的線程。
- 線程命名:創(chuàng)建的線程具有默認名稱前綴,通常形式為“pool-x-thread-y”,其中 x 和 y 是數(shù)字。
- 線程優(yōu)先級:線程優(yōu)先級設置為
Thread.NORM_PRIORITY
,這是 Java 線程的默認優(yōu)先級。 - 非守護線程:創(chuàng)建的線程是非守護線程,這意味著它們的存在將阻止 JVM 退出。
源代碼分析
defaultThreadFactory
方法的詳細實現(xiàn)未完全暴露,但我們可以從ThreadFactory
接口和一些可用的源代碼片段推斷其行為。
以下是defaultThreadFactory
方法的典型調用:
public static ThreadFactory defaultThreadFactory() { return new DefaultThreadFactory(); }
DefaultThreadFactory
是Executors
類中的私有靜態(tài)內部類,實現(xiàn)了ThreadFactory
接口。ThreadFactory
接口定義了newThread(Runnable r)
方法用于創(chuàng)建新線程。
實現(xiàn)過程
- 初始化:調用
defaultThreadFactory
方法時,返回一個新的DefaultThreadFactory
實例。 - 線程創(chuàng)建:當使用此工廠創(chuàng)建線程時,它調用
newThread(Runnable r)
方法。 - 線程命名:
newThread(Runnable r)
方法創(chuàng)建一個新的Thread
對象并設置默認線程名稱。 - 線程組分配:新線程被分配到一個默認線程組。
- 線程優(yōu)先級和守護狀態(tài):線程優(yōu)先級設置為默認值,如果初始為守護線程,則將其設置為非守護線程。
示例
雖然無法看到defaultThreadFactory
的精確實現(xiàn),但我們可以提供一個示例實現(xiàn)來演示如何創(chuàng)建具有默認屬性的線程:
public class DefaultThreadFactory implements ThreadFactory { private static final AtomicInteger poolNumber = new AtomicInteger(1); private final ThreadGroup group; private final AtomicInteger threadNumber = new AtomicInteger(1); private final String namePrefix; DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); group = (s!= null)? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; } public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); if (t.isDaemon()) t.setDaemon(false); if (t.getPriority()!= Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } }
在這個示例中,DefaultThreadFactory
使用AtomicInteger
確保池和線程編號的唯一性。創(chuàng)建的線程名稱具有前綴“pool-x-thread-y”,其中 x 和 y 是遞增的數(shù)字。線程是非守護的,其優(yōu)先級設置為Thread.NORM_PRIORITY
。
特性
- 標準線程屬性:使用
defaultThreadFactory
創(chuàng)建的線程具有標準的 Java 線程屬性。 - 非特殊用途:此線程工廠適用于不需要特殊權限的應用程序。
- 非守護線程:這些線程的存在將阻止 JVM 退出,直到所有非守護線程完成執(zhí)行。
使用場景
- 標準應用程序:適用于大多數(shù)需要具有默認屬性線程的標準應用程序。
- ExecutorService 實現(xiàn):在不需要特殊線程屬性時,通常用作
ExecutorService
實現(xiàn)的默認選擇。
unconfigurableExecutorService(ExecutorService executor)
unconfigurableExecutorService
方法在 Java java.util.concurrent
包的Executors
類中,用于創(chuàng)建一個圍繞ExecutorService
的不可配置包裝器。這意味著一旦包裝的ExecutorService
被創(chuàng)建,其配置就不能被更改,例如修改池大小或任務隊列。
實現(xiàn)原理
- 封裝:將現(xiàn)有的
ExecutorService
包裝在一個不可配置的代理中。 - 不可變配置:任何更改配置的方法調用,如
shutdown
、shutdownNow
、setCorePoolSize
等,都將拋出UnsupportedOperationException
。 - 委托:其他方法調用被委托給原始的
ExecutorService
。
源代碼分析
unconfigurableExecutorService
方法的詳細實現(xiàn)未完全暴露,因為它是Executors
類的私有方法的一部分。然而,我們可以根據(jù)ExecutorService
接口和代理機制推斷其行為。
以下是unconfigurableExecutorService
方法的典型調用:
public static ExecutorService unconfigurableExecutorService(ExecutorService executor) { return new FinalizableDelegatedExecutorService(executor); }
FinalizableDelegatedExecutorService
是Executors
類中的私有靜態(tài)內部類,實現(xiàn)了ExecutorService
接口,并將方法調用委托給另一個ExecutorService
。
實現(xiàn)過程
- 初始化:調用
unconfigurableExecutorService
方法時,返回一個新的FinalizableDelegatedExecutorService
實例,該實例將原始的ExecutorService
作為參數(shù)。 - 方法攔截:對
FinalizableDelegatedExecutorService
方法的調用首先被攔截。 - 配置修改攔截:如果方法是用于修改配置的,如
shutdown
或shutdownNow
,則拋出UnsupportedOperationException
。 - 委托其他調用:不涉及配置修改的調用,如
submit
或execute
,被委托給原始的ExecutorService
。
示例
以下是一個示例實現(xiàn),演示如何創(chuàng)建一個不可配置的ExecutorService
代理:
public class UnconfigurableExecutorService implements ExecutorService { private final ExecutorService executor; public UnconfigurableExecutorService(ExecutorService executor) { this.executor = executor; } @Override public void shutdown() { throw new UnsupportedOperationException("Shutdown not allowed"); } @Override public List<Runnable> shutdownNow() { throw new UnsupportedOperationException("Shutdown not allowed"); } @Override public boolean isShutdown() { return executor.isShutdown(); } @Override public boolean isTerminated() { return executor.isTerminated(); } @Override public void execute(Runnable command) { executor.execute(command); } }
在這個示例中,UnconfigurableExecutorService
攔截shutdown
和shutdownNow
方法并拋出UnsupportedOperationException
。其他方法直接委托給原始的ExecutorService
。
特性
- 不可變配置:創(chuàng)建的
ExecutorService
包裝器確保線程池的配置不能被外部更改。 - 共享環(huán)境中的安全性:有助于防止意外更改線程池的狀態(tài),提高多線程環(huán)境中的安全性。
- 維護原始行為:其他方法保留原始
ExecutorService
的行為。
使用場景
- 共享線程池:適用于多個組件共享同一個線程池的情況,防止一個組件意外修改配置。
- 受控環(huán)境:在需要線程池配置保持一致且不可更改的環(huán)境中很有用。
以上就是使用Java Executors創(chuàng)建線程池的9種方法的詳細內容,更多關于Java Executors創(chuàng)建線程池的資料請關注腳本之家其它相關文章!
相關文章
SpringBoot項目嵌入RocketMQ的實現(xiàn)示例
本文主要介紹了SpringBoot項目嵌入RocketMQ的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2024-05-05SpringBoot快速接入OpenAI大模型的方法(JDK8)
本文介紹了如何使用AI4J快速接入OpenAI大模型,并展示了如何實現(xiàn)流式與非流式的輸出,以及對函數(shù)調用的使用,AI4J支持JDK8,適用于多種應用場景,包括Spring Boot項目,感興趣的朋友一起看看吧2025-02-02spring security結合jwt實現(xiàn)用戶重復登錄處理
本文主要介紹了spring security結合jwt實現(xiàn)用戶重復登錄處理,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03