<JavaEE> 經典設計模式之 -- 線程池

目錄

一、線程池的概念

二、Java 標準庫中的線程池類

2.1 ThreadPoolExecutor 類

2.1.1?corePoolSize 和?maximumPoolSize

2.1.2?keepAliveTime 和?unit

2.1.3?workQueue

2.1.4?threadFactory

2.1.5?handler

2.1.6 創建一個參數自定義的線程池

2.2?Executors 類

2.3 實現自己的線程池


一、線程池的概念

1)什么是線程池?

準備預期需要使用的對象,將這些對象放入一個可以隨時取用的容器中,這個容器就被稱為“池”。

使用過的對象也不立刻銷毀,而是放回“池”中,以備下次使用。

將線程作為上述對象,放在一個容器中,這就稱為“線程池”。

2)為什么使用線程池?
在實際使用中,“線程池”并沒有頻繁的創建和銷毀線程,而是從“池”中存取線程,這樣可以減少每次啟動和銷毀線程的損耗,提高運行效率,減小系統開銷。
3)為什么使用線程池可以提高效率?

通常創建線程,是通過向系統申請創建,需要通過系統內核完成,是具有內核態的代碼。

而從線程池中存取線程,是屬于用戶態的代碼,相比于內核態代碼更可控、穩定,操作更快。


二、Java 標準庫中的線程池類

2.1 ThreadPoolExecutor 類

這個類的構造方法參數眾多,包含以下參數:

int corePoolSize

核心線程數

int maximumPoolSize

最大線程數

long keepAliveTime

空閑線程存活時間

TimeUnit unit

時間單位

BlockingQueue<Runnable> workQueue

任務隊列

ThreadFactory threadFactory

線程工廠

RejectedExecutionHandler handler

拒絕策略

2.1.1?corePoolSize 和?maximumPoolSize

int corePoolSize?核心線程數

線程池中保持持有的最小線程數量。

int maximumPoolSize?最大線程數

線程池中可以持有的最大線程數量。
標準庫提供的線程池,持有的線程數量是可以變動的,可以根據需要執行的任務數量,自適應線程的數量。

2.1.2?keepAliveTime 和?unit

long keepAliveTime?空閑線程存活時間

當線程池中的線程處于空閑狀態時,會等待 keepAliveTime 時間后自動關閉。

如果keepAliveTime為0,線程在執行完任務后則不會關閉。

TimeUnit unit?時間單位
keepAliveTime?空閑線程存活時間的時間單位。

2.1.3?workQueue

BlockingQueue<Runnable> workQueue?任務隊列

用于存儲等待執行的任務。當線程池中的線程數量達到最大值時,新任務將被添加到隊列中等待執行。

執行的任務應該是 Runnable 接口的實現類,

2.1.4?threadFactory

前置知識點:工廠模式

什么是工廠模式?

工廠模式(Factory Pattern)是一種創建型設計模式,它提供了一種在不指定具體類的情況下創建對象的接口。

工廠模式的核心思想是,將對象的創建過程抽象出來,使得使用者的創建與類的實例化過程解耦。

在工廠模式中,會實現一個工廠類,它提供一個創建對象的接口,而使用者只需要調用這個接口即可,工廠類會根據客戶端的請求,返回不同類型的對象。

threadFactory?具體指什么:

ThreadFactory threadFactory?線程工廠
通過工廠類創建線程對象(簡單理解就是通過這個類產出線程)。ThreadFactory 是一個接口,接口中只中有一個方法 newThread 方法,通過覆寫該方法獲得一個線程,同時可以給這個新線程設置一些屬性。

2.1.5?handler

RejectedExecutionHandler handler?拒絕策略
線程池異常處理器,也稱拒絕策略。這里的 handler 表示一個實現了 RejectedExecutionHandler 接口的實現類,傳入的 handler 參數決定了出現異常時,線程池如何處理異常。
有哪幾種拒絕策略,分別表示什么?
ThreadPoolExecutor.AbortPolicy當線程池滿時,如果新任務無法執行,則立即拋出 RejectedExecutionException 異常,是默認策略。
ThreadPoolExecutor.CallerRunspolicy當線程池滿時,如果新任務無法執行,則由調用線程自己執行新任務。
ThreadPoolExecutor.DiscardOldestPolicy當線程池滿時,如果新任務無法執行,則丟棄最早添加的任務,然后執行新任務。
ThreadPoolExecutor.DiscardPolicy當線程池滿時,如果新任務無法執行,則丟棄新任務,不執行。

2.1.6 創建一個參數自定義的線程池

創建并運行以下線程池和任務:

分析上述代碼運行結果:

2.2?Executors 類

1)簡單介紹 Executors 類
ThreadPoolExecutor 類參數較多,使用較復雜。因此,為方便使用,標準庫中又提供了?Executors 類。Executors 類是對?ThreadPoolExecutor 類進行了一層封裝,是一個工廠類,通過這個類創建出不同屬性的線程池對象。
2)簡單介紹常用的 Executors 類創建線程池的方法

newFixedThreadPool

創建固定線程數的線程池

newCachedThreadPool

創建線程數目動態增長的線程池

newSingleThreadExecutor

創建只包含單個線程的線程池

newScheduledThreadPool

創建可以定時執行任務的線程池
3)開發過程中應該使用?ThreadPoolExecutor 類還是使用 Executors 類?

ThreadPoolExecutor 類參數較多、可以自定義,這意味著使用這個類創建的線程池更靈活。

而?Executors 類相比 ThreadPoolExecutor 類多了一層封裝,部分參數已經設定好,這使得?Executors 類在使用上更便利。

這兩種選擇,前者更偏向于高度定制化的線程池,而后者偏向于通用性。兩者并無高下之分,各有偏向,使用者根據實際應用場景使用即可。

2.3 實現自己的線程池

線程池的使用有以下關鍵點:

<1>

線程池,肯定要有線程。在這里實現一個線程數量固定的線程池,就需要在這個類的構造方法中,根據輸入的參數 n ,新建 n 個線程。
<2>維護一個阻塞隊列,隊列持有需要執行的任務。
<3>提供一個 submit 方法,用于將任務添加到任務隊列中。
<4>線程池中的線程,也有自己的任務,就是不斷地掃描任務隊列,如果隊列中有任務,則取出任務后執行。
<5>注意新建的線程需要有合適的啟動時機。在以下實現中,我們讓線程一創建就啟動。

代碼演示線程池的實現:

class MyThreadPool{//創建一個用于存放任務的隊列;private BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(5);//構造方法,用于構造線程池。方法中需要將線程new出來;public MyThreadPool(int n){//設置線程需要執行的任務;Runnable runnable = new  Runnable() {@Overridepublic void run() {while (true){try {//從任務隊列中取出任務,并執行;queue.take().run();} catch (InterruptedException e) {e.printStackTrace();}}}};//循環創建線程,并啟動,將線程放入隊列中;for (int i = 0; i < n; i++){Thread t = new Thread(runnable);t.start();}}//添加任務方法。往任務隊列中添加任務;public void submit(Runnable runnable) throws InterruptedException {queue.put(runnable);}
}
public class ThreadPool_Demo35 {public static void main(String[] args) throws InterruptedException {//新建線程池;MyThreadPool threadPool = new MyThreadPool(2);//給線程池添加任務;for (int i= 0; i < 10; i++){int n = i;threadPool.submit(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + " 執行任務:" + n);}});}}
}//運行結果:
Thread-0 執行任務:0
Thread-1 執行任務:1
Thread-0 執行任務:2
Thread-1 執行任務:3
Thread-0 執行任務:4
Thread-0 執行任務:6
Thread-0 執行任務:7
Thread-0 執行任務:8
Thread-0 執行任務:9
Thread-1 執行任務:5
...十個任務全部成功打印。
應該注意到,線程沒有執行結束,還在等待新的任務加入,這是線程池的合理功能。

閱讀指針 -> 《 Synchronized 鎖進階》

鏈接生成中..........

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/210132.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/210132.shtml
英文地址,請注明出處:http://en.pswp.cn/news/210132.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

go學習筆記(17)Blob and ArrayBuffer

最近在學習go websocket的時候&#xff0c;在學習實驗過程遇到一個比較奇怪問題。為什么我的數據返回是blob&#xff0c;而不是arrayBuffer&#xff1f;百思不得其解。 直到同事打包的時候微信小游戲遇到了一個報錯。FileReader不支持。 經過在社區查詢&#xff0c;官方答復是…

Qt之QCache和QContiguousCache

一.QCache QCache在構造的時候指定了緩存中允許的最大成本,也就是如下構造函數中的參數maxCost。默認情況下,QCaches maxCost() 是100。 QCache(int maxCost = 100) ~QCache() void clear() bool contains(const Key &key) const int count() const bool insert(const …

[原創] 電源芯片輸出端的紋波測試

網上有很多文章講解&#xff0c;電源芯片的紋波測試&#xff0c;原理圖各種講解&#xff0c;理論有余&#xff0c;實質性測試細節不夠細致&#xff0c;想寫一些測試步驟&#xff0c;作為分享和記錄。 1、設置示波器參數 1.1 校準示波器 1.2 探頭按鈕推到X1&#xff08;代表波…

[RoBERTa]論文實現:RoBERTa: A Robustly Optimized BERT Pretraining Approach

文章目錄 一、完整代碼二、論文解讀2.1 模型架構2.2 參數設置2.3 數據2.4 評估 三、對比四、整體總結 論文&#xff1a;RoBERTa&#xff1a;A Robustly Optimized BERT Pretraining Approach 作者&#xff1a;Yinhan Liu, Myle Ott, Naman Goyal, Jingfei Du, Mandar Joshi, Da…

【Qt5】Q_UNUSED()

2023年12月9日&#xff0c;周六晚上 Q_UNUSED()是一個用于告訴編譯器不使用&#xff08;或者未使用&#xff09;特定變量的宏。 有時候&#xff0c;在函數簽名中聲明了某些參數&#xff0c;但是在函數體內并沒有使用它們。這可能是因為在某些情況下&#xff0c;函數可能需要接…

P10 Linux進程編程 fork創建子進程

目錄 前言 01 fork()創建子進程 示例 1使用 fork()創建子進程。 02 fork創建新進程時發生了什么事&#xff1f; 2.1 父、子進程中對應的文件描述符指向了相同的文件表 前言 &#x1f3ac; 個人主頁&#xff1a;ChenPi &#x1f43b;推薦專欄1: 《Linux C應用編程&#xf…

異步回調模式

異步回調 所謂異步回調&#xff0c;本質上就是多線程中線程的通信&#xff0c;如今很多業務系統中&#xff0c;某個業務或者功能調用多個外部接口&#xff0c;通常這種調用就是異步的調用。如何得到這些異步調用的結果自然也就很重要了。 Callable、Future、FutureTask publi…

半導體劃片機助力氧化鋁陶瓷片切割:科技與工藝的完美結合

在當今半導體制造領域&#xff0c;氧化鋁陶瓷片作為一種高性能、高可靠性的材料&#xff0c;被廣泛應用于各種電子設備中。而半導體劃片機的出現&#xff0c;則為氧化鋁陶瓷片的切割提供了新的解決方案&#xff0c;實現了科技與工藝的完美結合。 氧化鋁陶瓷片是一種以氧化鋁為基…

《巫師3》缺失vcomp110.dll如何解決,如何快速修復vcomp110.dll丟失問題

在日常使用電腦的過程中&#xff0c;我們可能會遇到一些錯誤提示&#xff0c;其中之一就是“vcomp110.dll丟失”。這個錯誤提示通常意味著vcomp110.dll文件在系統中無法找到或加載。那么&#xff0c;vcomp110.dll丟失的原因是什么&#xff1f;它對電腦有什么影響&#xff1f;本…

高德地圖vue實現自定義標點熱力圖效果(縮放時展示不同數據)

高德地圖插件引入省略。。。樣式和vue基礎組件省略。。。 如果每個標點沒有數值&#xff0c;則可以用點聚合來實現功能下面例子&#xff0c;每個標點會有按市統計的數值&#xff0c;而且縮放一定程度時&#xff0c;需要展示按省統計的標點&#xff0c;因此需要自定義標點樣式和…

leetcode刷題日志-54螺旋矩陣

思路&#xff1a; 上下左右設置四個邊界 每走完一行或者一列&#xff0c;移動相應邊界&#xff0c;當左邊界大于右邊界&#xff0c;或者上邊界大于下邊界時&#xff0c;結束 代碼如下&#xff1a; class Solution {public List<Integer> spiralOrder(int[][] matrix) {…

線程上下文切換

線程上下文切換 巧妙地利用了時間片輪轉的方式, CPU 給每個任務都服務一定的時間&#xff0c;然后把當前任務的狀態保存下來&#xff0c;在加載下一任務的狀態后&#xff0c;繼續服務下一任務&#xff0c;任務的狀態保存及再加載, 這段過程就叫做上下文切換。時間片輪轉的方式…

Determining Which Version of GDS is Installed

Determining Which Version of GDS is Installed To determine which version of GDS you have, run the following command: $ gdscheck.py -v Example output: GDS release version: 1.0.0.78 nvidia_fs version: 2.7 libcufile version: 2.4

冒泡排序和直接選擇排序(C/C++實現)

文章目錄 冒泡排序(交換排序&#xff09;基本思想特性總結代碼實現 直接選擇排序基本思想特性總結代碼實現&#xff08;優化&#xff0c;每次循環同時選擇最小和最大的數&#xff09; 冒泡排序(交換排序&#xff09; 基本思想 基本思想&#xff1a;所謂交換&#xff0c;就是根…

class065 A星、Floyd、Bellman-Ford與SPFA【算法】

class065 A星、Floyd、Bellman-Ford與SPFA【算法】 2023-12-9 19:27:02 算法講解065【必備】A星、Floyd、Bellman-Ford與SPFA code1 A*算法模版 // A*算法模版&#xff08;對數器驗證&#xff09; package class065;import java.util.PriorityQueue;// A*算法模版&#xff…

vue3+TypeScript全局事件總線mitt

在vue3中 $ on&#xff0c;$off 和 $once 實例方法已被移除&#xff0c;組件實例不再實現事件觸發接口&#xff0c;因此大家熟悉的EventBus便無法使用了。然而我們習慣了使用EventBus&#xff0c;對于這種情況我們可以使用Mitt庫 npm i mitt -S 首先要在全局掛載 mitt 在app…

兩年外包生涯做完,感覺自己廢了一半。。。。。

先說一下自己的情況&#xff0c;本科生&#xff0c;19年通過校招進入南京某軟件公司&#xff0c;干了接近2年的功能測試&#xff0c;今年年初&#xff0c;感覺自己不能夠在這樣下去了&#xff0c;長時間呆在一個舒適的環境會讓一個人墮落!而我已經在一個企業干了2年的功能測試&…

laravel的ORM 對象關系映射

Laravel 中的 ORM&#xff08;Eloquent ORM&#xff09;是 Laravel 框架內置的一種對象關系映射系統&#xff0c;用于在 PHP 應用中與數據庫進行交互。Eloquent 提供了一種優雅而直觀的語法&#xff0c;使得開發者可以使用面向對象的方式進行數據庫查詢和操作。 定義模型&…

結合ColorUI組件開發微信小程序

1.自定義組件生命周期函數&#xff1a; Component({data: {},attached() {console.log("自定義組件生命周期函數 attached--先執行");this.getPos();},ready() {console.log("ready生命周期函數---在attached之后執行")},methods: {getPos() {var that th…

數據結構:位圖、布隆過濾器以及海量數據面試題

位圖、布隆過濾器以及海量數據面試題 1.位圖1.1概念1.2實現1.3位圖應用 2.布隆過濾器2.1布隆過濾器的提出2.2布隆過濾器的概念2.3布隆過濾器的查找2.4布隆過濾器的實現2.5布隆過濾器的刪除2.6布隆過濾器的優點2.7布隆過濾器的缺點 3.海量數據面試題3.1哈希切分3.2位圖應用3.3布…