【并發編程篇】源碼分析,手動創建線程池

文章目錄

  • 🛸前言
    • 🌹Executors的三大方法
  • 🍔簡述線程池
  • 🎆手動創建線程池
    • ?源碼分析
    • ?代碼實現,手動創建線程池
      • 🎈CallerRunsPolicy()
      • 🎈AbortPolicy()
      • 🎈DiscardPolicy()
      • 🎈DiscardOldestPolicy()

在這里插入圖片描述

🛸前言

🌹Executors的三大方法

Java 中的 Executors 類提供了創建和管理線程池的工廠方法。主要有以下三種常用的靜態工廠方法:

  • newFixedThreadPool(int nThreads):固定的線程池大小
    創建一個固定大小的線程池,其中包含指定數量的線程。如果所有線程都處于活動狀態,并且任務隊列已滿,那么新任務將在任務隊列中等待,直到有空閑的線程可用。
    在這里插入圖片描述

  • newCachedThreadPool():遇強則強,遇弱則弱
    創建一個可緩存的線程池,如果線程池的當前規模超過處理需求時,它會回收空閑線程;當需求增加時,則可以添加新的線程,線程池規模不存在限制。

在這里插入圖片描述

  • newSingleThreadExecutor(): 單個線程
    創建一個單線程的線程池,該線程池只有一個工作線程,它保證所有任務按順序執行。

在這里插入圖片描述

這些工廠方法都返回實現了 ExecutorService 接口的 ThreadPoolExecutor 對象,這是 Java 線程池的一個具體實現,提供了對線程池的操作和控制。通過使用這些工廠方法創建線程池,可以方便快捷地滿足不同場景下的線程管理需求。


請添加圖片描述
由于使用Executors不安全,那么我們需要手動創建一個線程池

🍔簡述線程池

線程池是一種用于管理和重用線程的機制,它通過預先創建一組線程,并將任務提交給這些線程來執行。線程池可以有效地控制并發線程的數量,避免了頻繁創建和銷毀線程的開銷,提高了系統的性能和資源利用率。

線程池通常由以下組件構成:

  • 線程池管理器(ThreadPoolExecutor):負責創建、管理和調度線程池中的線程。它維護著一個線程池的狀態,包括線程數量、任務隊列、線程工廠等屬性。
  • 工作線程(Worker Thread):線程池中的實際執行任務的線程。線程池會創建一定數量的工作線程,每個工作線程可以執行多個任務。
  • 任務隊列(Task Queue):用于存儲待執行的任務。當線程池中的線程空閑時,它們會從任務隊列中獲取任務并執行。
  • 線程工廠(Thread Factory):用于創建新的線程對象。線程池在需要創建新線程時,會使用線程工廠創建線程對象。

線程池的主要優點包括:

  • 提高系統性能:線程池可以控制并發線程的數量,避免了過多的線程競爭和頻繁的線程創建銷毀開銷,提高了系統的性能。
  • 提高資源利用率:線程池可以重用線程,避免了線程創建和銷毀的開銷,提高了系統的資源利用率。
  • 提供線程管理和監控:線程池提供了對線程的管理和監控機制,可以方便地查看線程池的狀態、線程執行情況等信息,便于調優和排查問題。

使用線程池時,需要根據具體的業務需求和系統資源情況合理配置線程池的大小、任務隊列的容量以及其他相關參數,避免因線程池過小或過大導致的性能問題。

🎆手動創建線程池

?源碼分析

newSingleThreadExecutor的源碼
在這里插入圖片描述newFixedThreadPool的源碼
在這里插入圖片描述newCachedThreadPool的源碼
在這里插入圖片描述其中有個參數長度是Integer,MAX_VALUE,長度過大,可能會堆積大量的請求,對應了上面我們說的不能用Executors,而要用ThreadPoolExecutors

我們發現,上面三者的源碼中都有ThreadPoolExecutor
說明調用線程的本質調用的是ThreadPoolExecutor

下面我們來分析一下ThreadPoolExecutor
在這里插入圖片描述在這里插入圖片描述下面我們來想象一個場景,來更好的理解線程池
比如我們去銀行辦理業務
銀行有5個窗口,但是只打開了2個(代表核心線程池的大小為2),還有3個沒有開(觸發最大并發量的情況下才會打開這3個窗口),還有容量為3的候客區(阻塞隊列)
然后有用戶去辦理業務了,假如來了3個用戶,2個去窗口了,還有1個在候客區等待,此時,又來了3個用戶,這時候客區的位置不夠了(阻塞隊列滿了),就要打開那關閉的3個窗口(觸發最大并發量了)

?代碼實現,手動創建線程池

🎈CallerRunsPolicy()

package org.Test6;import java.util.concurrent.*;public class Demo01 {public static void main(String[] args) {//自定義線程池ExecutorService threadPool = new ThreadPoolExecutor(2,5,3,TimeUnit.SECONDS,   //超時等待時間new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy());try {for (int i = 1; i <= 10; i++) {//使用線程池后,使用線程池來創建線程threadPool.execute(()->{System.out.println(Thread.currentThread().getName()+"ok");});}}catch (Exception e){e.printStackTrace();}finally {//關閉線程池threadPool.shutdown();}}
}

在這里插入圖片描述

代碼里面的超時等待時間是什么意思
我們對應上面去銀行的場景,觸發最大并發條件后,所有窗口都打開了,一段時間后,所有用戶都離開了,過了設定的時間都沒有業務,那么后面3個窗口就要關閉

🎈AbortPolicy()

package org.Test6;import java.util.concurrent.*;public class Demo01 {public static void main(String[] args) {//自定義線程池ExecutorService threadPool = new ThreadPoolExecutor(2,5,3,TimeUnit.SECONDS,   //超時等待時間new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());try {for (int i = 1; i <= 10; i++) {//使用線程池后,使用線程池來創建線程threadPool.execute(()->{System.out.println(Thread.currentThread().getName()+"ok");});}}catch (Exception e){e.printStackTrace();}finally {//關閉線程池threadPool.shutdown();}}
}

在這里插入圖片描述

🎈DiscardPolicy()

package org.Test6;import java.util.concurrent.*;public class Demo01 {public static void main(String[] args) {//自定義線程池ExecutorService threadPool = new ThreadPoolExecutor(2,5,3,TimeUnit.SECONDS,   //超時等待時間new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardPolicy());try {for (int i = 1; i <= 10; i++) {//使用線程池后,使用線程池來創建線程threadPool.execute(()->{System.out.println(Thread.currentThread().getName()+"ok");});}}catch (Exception e){e.printStackTrace();}finally {//關閉線程池threadPool.shutdown();}}
}

丟掉任務,但是不會拋出異常

在這里插入圖片描述

🎈DiscardOldestPolicy()

package org.Test6;import java.util.concurrent.*;public class Demo01 {public static void main(String[] args) {//自定義線程池ExecutorService threadPool = new ThreadPoolExecutor(2,5,3,TimeUnit.SECONDS,   //超時等待時間new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardOldestPolicy());try {for (int i = 1; i <= 10; i++) {//使用線程池后,使用線程池來創建線程threadPool.execute(()->{System.out.println(Thread.currentThread().getName()+"ok");});}}catch (Exception e){e.printStackTrace();}finally {//關閉線程池threadPool.shutdown();}}
}

在這里插入圖片描述

在技術的道路上,我們不斷探索、不斷前行,不斷面對挑戰、不斷突破自我。科技的發展改變著世界,而我們作為技術人員,也在這個過程中書寫著自己的篇章。讓我們攜手并進,共同努力,開創美好的未來!愿我們在科技的征途上不斷奮進,創造出更加美好、更加智能的明天!

在這里插入圖片描述

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

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

相關文章

LNPMariadb數據庫分離|web服務器集群

LNP&Mariadb數據庫分離&#xff5c;web服務器集群 網站架構演變單機版LNMP獨立數據庫服務器web服務器集群與Session保持 LNP與數據庫分離1. 準備一臺獨立的服務器&#xff0c;安裝數據庫軟件包2. 將之前的LNMP網站中的數據庫遷移到新的數據庫服務器3. 修改wordpress網站配置…

2023.12.24 關于 Redis 中 String 類型內部編碼 及 應用場景

目錄 String 類型內部編碼 3 種內部編碼方式 String 類型應用場景 Cache 緩存 鍵名命名規則 計數&#xff08;Counter&#xff09; 共享會話&#xff08;Session &#xff09; 手機驗證碼 總結 String 類型內部編碼 3 種內部編碼方式 int&#xff1a;用來表示 64 位 —…

vue3菜單權限管理實現

前提 你的菜單是根據路由動態生成的&#xff0c;具體可以參考這篇博客對el-menu組件進行遞歸封裝&#xff08;根據路由配置動態生成&#xff09; 描述 首先將路由分為常量路由constantRoute&#xff08;所有用戶都有的路由&#xff09;和異步路由asyncRoute&#xff08;需要動…

Gradle 插件

自定義Gradle插件 - 簡書

小天使的小難題:新生兒疝氣的關注與溫馨呵護

引言&#xff1a; 新生兒疝氣是一種在出生后可能出現的常見情況&#xff0c;雖然通常不會造成長期影響&#xff0c;但對于家長而言&#xff0c;了解如何正確應對新生兒疝氣是至關重要的。本文將深入探討新生兒疝氣的原因、癥狀&#xff0c;以及家長在面對這一問題時應該采取的…

1224. 交換瓶子(藍橋杯/圖論)

題目&#xff1a; 1224. 交換瓶子 - AcWing題庫 輸入樣例1&#xff1a; 5 3 1 2 5 4輸出樣例1&#xff1a; 3輸入樣例2&#xff1a; 5 5 4 3 2 1輸出樣例2&#xff1a; 2 思路&#xff1a;圖論 1.將對應的位置與當前的瓶子序列相連形成環。 2.最少交換次數能形成的最多…

Vue中的事件委托(事件代理)使用方法介紹

事件委托&#xff08;事件代理&#xff09; 將原本需要綁定在子元素上的事件監聽器委托在父元素上&#xff0c;讓父元素充當事件監聽的職務。 事件委托是一種利用事件冒泡的特性&#xff0c;在父節點上響應事件&#xff0c;而不是在子節點上響應事件的技術。它能夠改善性能&a…

如何理解JDK、JRE、JVM區別與聯系

摘要&#xff1a;JDK是 Java 語言的軟件開發工具包(SDK)。在JDK的安裝目錄下有一個jre目錄&#xff0c;里面有兩個文件夾bin和lib&#xff0c;在這里可以認為bin里的就是jvm&#xff0c;lib中則是jvm工作所需要的類庫&#xff0c;而jvm和 lib合起來就稱為jre。 一、JDK JDK(Ja…

【【迭代16次的CORDIC算法-verilog實現】】

迭代16次的CORDIC算法-verilog實現 -32位迭代16次verilog代碼實現 CORDIC.v module cordic32#(parameter DATA_WIDTH 8d32 , // we set data widthparameter PIPELINE 5d16 // Optimize waveform)(input …

第十四章Java博客

lambda就是數學中的“λ”的讀音&#xff0c;lambda表達式是基于λ演算而得名的&#xff0c;因為lambda抽象&#xff08;lambda abstraction&#xff09;表示一個匿名的函數&#xff0c;于是開發語言也將lambda表達式用來表示匿名函數&#xff0c;也就是沒有函數名字的函數。C#…

maven管理工具使用package打包的時候無法將lib文件夾下的第三方jar包打入,上線打jar包后運行異常問題

問題描述&#xff1a; 調用第三方接口的時候通過手動引入了第三方的兩個jar包到我本項目的lib文件夾下&#xff0c;并在pom文件添加入下配置&#xff1a; <dependency><groupId>cn.xxxx.xxxx.core</groupId><artifactId>xxxx-core</artifactId>…

Spring Boot 中實現跨域的幾種方式

前言 在現代Web應用中&#xff0c;由于安全性和隱私的考慮&#xff0c;瀏覽器限制了從一個域向另一個域發起的跨域HTTP請求。解決這個問題的一種常見方式是實現跨域資源共享&#xff08;CORS&#xff09;。Spring Boot提供了多種方式來處理跨域請求&#xff0c;本文將介紹其中的…

C語言字符串處理提取時間(ffmpeg返回的時間字符串)

【1】需求 需求&#xff1a;有一個 “00:01:33.90” 這樣格式的時間字符串&#xff0c;需要將這個字符串的時間值提取打印出來&#xff08;提取時、分、秒、毫秒&#xff09;。 這個時間字符串從哪里來的&#xff1f; 是ffmpeg返回的時間&#xff0c;也就是視頻的總時間。 下…

vs快捷鍵

ctrlMo 折疊代碼塊 ctrlML 打開代碼塊

電子電器架構(E/E)演化 —— 主流主機廠域集中架構概述

電子電器架構(E/E)演化 —— 主流主機廠域集中架構概述 我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 屏蔽力是信息過載時代一個人的特殊競爭力,任何消耗你的人和事,多看一眼都是你的不對。…

系列七(實戰)、發送 接收單向消息(Java操作RocketMQ)

一、發送 & 接收單向消息 1.1、概述 發送單向消息&#xff0c;適用于發送方不關心或者不在意消息的發送結果&#xff0c;這種方式的吞吐量很大&#xff0c;但是存在消息丟失的風險&#xff0c;對于重要消息要慎用&#xff01;該種方式通常適用于對消息沒有那么嚴格的場景中…

類和對象的創建和實例化

1. 類的概述 1.1 具體示例 類是描述一類事物的特征和行為的統稱&#xff0c;抽象的不存在的&#xff0c;泛指的概念&#xff0c;例如&#xff1a;描述一個人&#xff0c;從外觀上&#xff08;特征&#xff09;和言行舉止&#xff08;行為&#xff09;上進行描述外觀上&#xff…

c 語言學習:輸出階乘的算式

c 語言學習&#xff1a;輸出階乘的算式 代碼 #include "stdio.h"int fact(int num){if (num < 1){printf("1 ");return 1;} else {printf("%d x ",num);return num * fact(num-1);} }int main(){int num 10; // printf("plz inpu…

【華為OD題庫-107】編碼能力提升計劃-java

題目 為了提升軟件編碼能力&#xff0c;小王制定了刷題計劃&#xff0c;他選了題庫中的n道題&#xff0c;編號從0到n-1&#xff0c;并計劃在m天內按照題目編號順序刷完所有的題目(注意&#xff0c;小王不能用多天完成同一題) 在小王刷題計劃中&#xff0c;小王需要用time[i]的時…

老鷹目標檢測數據集VOC格式60張

老鷹是天空中的王者&#xff0c;它們擁有極佳的飛行能力。它們能以驚人的速度在天空中翱翔&#xff0c;尤其擅長高空俯沖捕食。老鷹的視力非常敏銳&#xff0c;能夠準確地發現地面上的獵物&#xff0c;并迅速下落抓取。它們的爪子強而有力&#xff0c;足以擊倒比自己體型龐大的…