什么是線程池?
線程池是一種用于管理和復用線程的機制,旨在減少線程的創建和銷毀次數,提高線程的可重用性和執行效率。通過線程池,可以控制線程的數量、數量大小以及線程的執行方式,從而更加有效地處理并發任務。
線程池的好處?
- 降低系統開銷:減少了線程的創建和銷毀次數,減少了系統資源的開銷。
- 提高響應速度:線程池中的線程預先創建好,可以立即執行任務,提高了系統的響應速度。
- 精細的調優:可以通過配置線程池的參數,如核心線程數、最大線程數、任務隊列等,來靈活地控制線程執行的規模和調度方式。
常用的線程池?
1、FixedThreadPool(固定大小線程池):
- 固定大小的線程池,線程數量一旦達到設定的核心線程數,就保持不變。
- 如果有任務提交時,如果空閑線程可以處理,則立即處理;如果沒有空閑線程,則任務進入隊列等待。
- 適用于需要限制線程數量的場景,比如數據庫連接池等。
2、CachedThreadPool(緩存線程池):
- 線程數量根據需要自動調整,沒有核心線程,最大線程數為 Integer.MAX_VALUE。
- 如果有空閑線程可用,則復用空閑線程;沒有則動態創建新線程。
- 適用于執行大量短期異步任務的場景。
3、SingleThreadPool(單線程池):
- 只有一個線程在工作,保證所有任務按照指定順序執行。
- 如果這個線程異常結束,會創建一個新的線程代替它,保證順序執行。
- 適用于需要順序執行任務的場景。
4、ScheduledThreadPool(定時任務線程池):
- 用于執行定時任務和周期性任務。
- 可以指定核心線程數量,可以根據需要動態調整線程數量。
線程池的七個參數?
1、核心線程數(corePoolSize):
- 核心線程數指的是線程池中保持存活的線程數量,即使線程處于空閑狀態也會保持存活,除非設置了允許核心線程超時。
2、最大線程數(maximumPoolSize):
- 最大線程數表示線程池中最大允許存在的線程數量,當任務達到一定數量時,線程池會創建新的線程來處理任務,直到達到最大線程數為止。
3、線程空閑時間(keepAliveTime):
- 線程空閑時間表示當線程處于空閑狀態時,等待新任務的最長時間,超過這個時間會被回收銷毀,只保留核心線程數的線程。也稱為線程的存活時間。
4、時間單位(unit):
- 時間單位用來指定 keepAliveTime 的單位,可以是秒、毫秒等。
5、工作隊列(workQueue):
- 工作隊列用來存儲線程池等待執行的任務,有不同的實現方式,如 LinkedBlockingQueue、ArrayBlockingQueue、SynchronousQueue 等。
6、線程工廠(threadFactory):
- 線程工廠用來創建新線程,可以自定義線程工廠來為線程池創建定制化的線程。
7、拒絕策略(handler):
拒絕策略用來指定當任務無法被線程池執行時的處理方式,有多種預定義的策略可供選擇,默認是 AbortPolicy。一共有四種拒絕策略:
- AbortPolicy(中止策略):
????????默認的拒絕策略。當線程池無法接受新任務時,會拋出 RejectedExecutionException 異常通知調用者任務無法繼續提交。
- CallerRunsPolicy(調用者運行策略):
????????如果線程池無法接受新任務,則由主線程(提交任務的線程)自己執行這個任務。這種策略不會拋棄任務,而是直接在主線程中執行。
- DiscardPolicy(丟棄策略):
????????當線程池無法接受新任務時,不做任何處理,直接丟棄無法執行的任務。
- DiscardOldestPolicy(丟棄最老的任務策略):
????????當線程池無法接受新任務時,丟棄最早加入工作隊列但尚未被執行的任務,然后嘗試將新任務添加到隊列中。
如何創建線程池?
1、手動創建 ThreadPoolExecutor 對象:
- 可以通過直接創建 ThreadPoolExecutor 對象來自定義線程池的各種參數,如核心線程數、最大線程數、工作隊列類型等。
- 通過構造函數 new ThreadPoolExecutor() 可以自定義線程池的各項參數,實現靈活的線程池管理。
2、Executors 工廠方法:
- Executors 類提供了一系列靜態工廠方法快速創建常見類型的線程池,如 newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor 等。
- 這些工廠方法可以方便地創建不同類型的線程池,簡化了線程池的創建過程,但有時可能會因為一些默認參數而不適用于特定場景。
3、ScheduledExecutorService 創建定時任務線程池:
- ScheduledExecutorService 是一個支持定時任務和周期性任務執行的線程池。通過 Executors.newScheduledThreadPool() 方法創建。
- 可以執行定時任務和周期性任務,具有方便的定時執行功能。
4、ForkJoinPool 創建并行任務線程池:
- ForkJoinPool 是 Java 7 中引入的用于支持并行任務執行的線程池,適用于拆分任務并行執行的場景。
- 通過 new ForkJoinPool() 構造方法創建,并通過 ForkJoinTask 提交任務。
線程池的執行流程?
為什么阿里的Java開發規范中禁止使用Executors創建線程池?
1、FixedThreadPool和SingleThreadPool
????????這兩種線程池都使用無界的 LinkedBlockingQueue 作為任務隊列,當請求隊列長度無限制時(Integer.MAX_VALUE),如果請求產生過快,可能會導致請求堆積,消耗大量內存資源,最終導致內存溢出。
2、CachedThreadPool和ScheduledThreadPool
????????這兩種線程池使用的是 SynchronousQueue,且線程數量上限為 Integer.MAX_VALUE。如果系統中的任務量過大,可能會導致大量線程被創建,這會消耗大量系統資源,包括內存和 CPU 資源,最終也可能導致內存溢出。
3、線程池的拒絕策略可能不當
Executors創建的線程池默認的拒絕策略是拋出RejectedExecutionException異常,這可能會導致任務提交者無法得到合理的反饋,而采用更合理的拒絕策略需要自定義ThreadPoolExecutor。
ps:以下是我整理的java面試資料,密碼是obht,感興趣的可以看看。最后,創作不易,覺得寫得不錯的可以點點關注!
鏈接:https://www.yuque.com/u39298356/uu4hxh?# 《Java面試寶典》?