35.Java線程池(線程池概述、線程池的架構、線程池的種類與創建、線程池的底層原理、線程池的工作流程、線程池的拒絕策略、自定義線程池)

一、線程池概述

1、線程池的優勢
  • 線程池是一種線程使用模式,線程過多會帶來調度開銷,進而影響緩存局部性和整體性能,而線程池維護著多個線程,等待著監督管理者分配可并發執行的任務,這避免了在處理短時間任務時創建與銷毀線程的代價,線程池不僅能夠保證內核的充分利用,還能防止過分調度

  • 線程池的工作主要是控制運行的線程數量,在處理過程中將任務放入隊列,然后在線程創建后啟動這些任務,如果線程數量超過了最大數量,超出數量的線程排隊等候,等其他線程執行完畢,再從隊列中取出任務來執行

2、線程池的特點
  • 降低資源消耗: 通過重復利用已創建的線程降低線程創建和銷毀造成的銷耗

  • 提高響應速度: 當任務到達時,任務可以不需要等待線程創建就能立即執行

  • 提高線程的可管理性: 線程是稀缺資源,如果無限制的創建,不僅會銷耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一的分配,調優和監控


二、線程池的架構

  • Java 中的線程池是通過 Executor 框架實現的,該框架中用到了 Executor 接口,Executors 類,ExecutorService 類,ThreadPoolExecutor 類

三、線程池的種類與創建

1、一池 N 線程
(1)基本介紹
  • 線程池中的線程處于一定的量,可以很好的控制線程的并發量

  • 線程可以重復被使用,在顯示關閉之前,都將一直存在

  • 超出一定量的線程被提交時候需在隊列中等待

(2)創建方式
ExecutorService threadPool = Executors.newFixedThreadPool(5);
(3)適用場景
  • 適用于可以預測線程數量的業務,或者服務器負載較重,對線程數有嚴格限制的場景
(4)基本使用
  • 使用 5 個窗口處理 10 個顧客請求
ExecutorService threadPool = Executors.newFixedThreadPool(5);try {for (int i = 1; i <= 10; i++) {// 執行線程threadPool.execute(() -> {System.out.println(Thread.currentThread().getName()+" 辦理業務");});}
} catch (Exception e) {e.printStackTrace();
} finally {// 關閉線程threadPool.shutdown();
}
  • 結果
pool-1-thread-1 辦理業務
pool-1-thread-5 辦理業務
pool-1-thread-4 辦理業務
pool-1-thread-3 辦理業務
pool-1-thread-2 辦理業務
pool-1-thread-3 辦理業務
pool-1-thread-4 辦理業務
pool-1-thread-5 辦理業務
pool-1-thread-1 辦理業務
pool-1-thread-2 辦理業務
2、一池一線程
(1)基本介紹
  • 線程池中最多執行一個線程,之后提交的線程活動將會排在隊列中依次執行
(2)創建方式
ExecutorService threadPool = Executors.newSingleThreadExecutor();
(3)適用場景
  • 適用于需要保證順序執行各個任務,并且在任意時間點,不會同時有多個線程的場景
(4)基本使用
  • 使用 1 個窗口處理 10 個顧客請求
ExecutorService threadPool = Executors.newSingleThreadExecutor();try {for (int i = 1; i <= 10; i++) {// 執行線程threadPool.execute(() -> {System.out.println(Thread.currentThread().getName()+" 辦理業務");});}
} catch (Exception e) {e.printStackTrace();
} finally {// 關閉線程threadPool.shutdown();
}
  • 結果
pool-1-thread-1 辦理業務
pool-1-thread-1 辦理業務
pool-1-thread-1 辦理業務
pool-1-thread-1 辦理業務
pool-1-thread-1 辦理業務
pool-1-thread-1 辦理業務
pool-1-thread-1 辦理業務
pool-1-thread-1 辦理業務
pool-1-thread-1 辦理業務
pool-1-thread-1 辦理業務
3、一池可擴容線程
(1)基本介紹
  • 線程池中數量沒有固定,可達到最大值為 Interger. MAX_VALUE

  • 線程池中的線程可進行緩存重復利用和回收,默認回收時間為一分鐘

  • 當線程池中沒有可用線程時,會重新創建一個線程

(2)創建方式
ExecutorService threadPool = Executors.newCachedThreadPool();
(3)適用場景
  • 適用于創建一個可無限擴大的線程池,服務器負載壓力較輕,執行時間較短,任務多的場景
(4)基本使用
  • 處理 20 個顧客請求
ExecutorService threadPool = Executors.newCachedThreadPool();try {for (int i = 1; i <= 20; i++) {// 執行線程threadPool.execute(() -> {System.out.println(Thread.currentThread().getName()+" 辦理業務");});}
} catch (Exception e) {e.printStackTrace();
} finally {// 關閉線程threadPool.shutdown();
}
  • 結果
pool-1-thread-1 辦理業務
pool-1-thread-4 辦理業務
pool-1-thread-3 辦理業務
pool-1-thread-2 辦理業務
pool-1-thread-6 辦理業務
pool-1-thread-5 辦理業務
pool-1-thread-8 辦理業務
pool-1-thread-7 辦理業務
pool-1-thread-3 辦理業務
pool-1-thread-4 辦理業務
pool-1-thread-7 辦理業務
pool-1-thread-5 辦理業務
pool-1-thread-1 辦理業務
pool-1-thread-2 辦理業務
pool-1-thread-6 辦理業務
pool-1-thread-8 辦理業務
pool-1-thread-3 辦理業務
pool-1-thread-9 辦理業務
pool-1-thread-7 辦理業務
pool-1-thread-5 辦理業務

四、線程池的底層原理

1、ThreadPoolExecutor 類
  • 通過查看上面三種方式創建線程池對象的源代碼,發現都有 new ThreadPoolExecutor 操作,具體查看該類的源代碼,其構造器涉及七個參數
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.acc = System.getSecurityManager() == null ?null :AccessController.getContext();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;
}
2、ThreadPoolExecutor 構造器涉及的七個參數
  1. int corePoolSize:常駐線程數量

  2. int maximumPoolSize:最大線程數量

  3. long keepAliveTime:空閑線程存活時間

  4. TimeUnit unit:空閑線程存時間單位

  5. BlockingQueue workQueue:阻塞隊列,存放提交但未執行任務

  6. ThreadFactory threadFactory:線程工廠,用于創建線程(可省略)

  7. RejectedExecutionHandler handler:阻塞隊列滿時的拒絕策略(可省略)


五、線程池的工作流程

  • 在創建了線程池后,線程池中的線程數為零

  • 當調用 execute 方法添加一個請求任務時,線程池會做如下判斷

    1. 如果正在運行的線程數量小于 corePool 的線程數量,那么馬上創建線程運行這個任務

    2. 如果正在運行的線程數量大于或等于 corePool 的線程數量,那么將這個任務存入阻塞隊列

    3. 如果這個時候隊列已滿且正在運行的線程數量小于 maximumPool 的線程數量,則創建非核心線程立刻運行這個任務

    4. 如果隊列已滿且正在運行的線程數量大于或等于 maximumPool 的線程數量,那么線程池會啟動拒絕策略

  • 當一個線程完成任務時,它會從隊列中取下一個任務來執行

  • 當一個線程空閑超過一定的時間時,會做如下判斷

    1. 如果當前運行的線程數大于 corePool 的線程數量,那么這個線程就被停掉

    2. 線程池的所有任務完成后,最終會收縮到 corePool 的大小


六、線程池的拒絕策略

1、 AbortPolicy
  • 默認的拒絕策略,會直接拋出 RejectedExecutionException 異常阻止系統正常運行
2、DiscardPolicy
  • 該策略會丟棄無法處理的任務,不給予任何處理也不拋出異常,如果允許任務丟失,這是最好的一種策略
3、DiscardOldestPolicy
  • 丟棄隊列中等待最久的任務,然后把當前任務存入隊列中,并嘗試提交當前任務
4、CallerRunsPolicy
  • 該策略既不會丟棄任務,也不會拋出異常,而是將任務退回給調用者

七、自定義線程池

1、Executors 返回的線程池對象的弊端
  • FixedThreadPool 和 SingleThreadExecutor 允許請求隊列的長度為 Interger.MAX_VALUE,可能會堆積大量異常, 從而導致 OOM

  • CachedThreadPool 允許的創建線程數量為 Interger.MAX_VALUE,可能會創建大量線程,從而導致 OOM

2、具體實現
package com.my.pool;import java.util.concurrent.*;public class MyThreadPoolTest {public static void main(String[] args) {ExecutorService threadPool = new ThreadPoolExecutor(2,5,2L,TimeUnit.SECONDS,new ArrayBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardOldestPolicy());// 處理 10 個顧客請求try {for (int i = 1; i <= 10; i++) {// 執行線程threadPool.execute(() -> {System.out.println(Thread.currentThread().getName()+" 辦理業務");});}} catch (Exception e) {e.printStackTrace();} finally {// 關閉線程threadPool.shutdown();}}
}
  • 結果
pool-1-thread-1 辦理業務
pool-1-thread-4 辦理業務
pool-1-thread-3 辦理業務
pool-1-thread-2 辦理業務
pool-1-thread-3 辦理業務
pool-1-thread-4 辦理業務
pool-1-thread-1 辦理業務
pool-1-thread-5 辦理業務

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

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

相關文章

驅動開發硬核特訓 · Day 6 : 深入解析設備模型的數據流與匹配機制 —— 以 i.MX8M 與樹莓派為例的實戰對比

&#x1f50d; B站相應的視屏教程&#xff1a; &#x1f4cc; 內核&#xff1a;博文視頻 - 從靜態綁定驅動模型到現代設備模型 主題&#xff1a;深入解析設備模型的數據流與匹配機制 —— 以 i.MX8M 與樹莓派為例的實戰對比 在上一節中&#xff0c;我們從驅動框架的歷史演進出…

Blender安裝基礎使用教程

本博客記錄安裝Blender和基礎使用&#xff0c;可以按如下操作來繪制標靶場景、道路標識牌等。 目錄 1.安裝Blender 2.創建面板資源 步驟 1: 設置 Blender 場景 步驟 2: 創建一個平面 步驟 3: 將 PDF 轉換為圖像 步驟 4-方法1: 添加材質并貼圖 步驟4-方法2&#xff1a;創…

智能手機功耗測試

隨著智能手機發展,用戶體驗對手機的續航功耗要求越來越高。需要對手機進行功耗測試及分解優化,將手機的性能與功耗平衡。低功耗技術推動了手機的用戶體驗。手機功耗測試可以采用powermonitor或者NI儀表在功耗版上進行測試與優化。作為一個多功能的智能終端,手機的功耗組成極…

從代碼學習深度學習 - 多頭注意力 PyTorch 版

文章目錄 前言一、多頭注意力機制介紹1.1 工作原理1.2 優勢1.3 代碼實現概述二、代碼解析2.1 導入依賴序列掩碼函數2.2 掩碼 Softmax 函數2.3 縮放點積注意力2.4 張量轉換函數2.5 多頭注意力模塊2.6 測試代碼總結前言 在深度學習領域,注意力機制(Attention Mechanism)是自然…

學術版 GPT 網頁

學術版 GPT 網頁 1. 學術版 GPT 網頁非盈利版References https://academic.chatwithpaper.org/ 1. 學術版 GPT 網頁非盈利版 arXiv 全文翻譯&#xff0c;免費且無需登錄。 更換模型 System prompt: Serve me as a writing and programming assistant. 界面外觀 References …

MarkDown 輸出表格的方法

MarkDown用來輸出表格很簡單&#xff0c;比Word手搓表格簡單多了&#xff0c;而且方便修改。 MarkDown代碼&#xff1a; |A|B|C|D| |:-|-:|:-:|-| |1|b|c|d| |2|b|c|d| |3|b|c|d| |4|b|c|d| |5|b|c|d|顯示效果&#xff1a; ABCD1bcd2bcd3bcd4bcd5bcd A列強制左對齊&#xf…

MetaGPT深度解析:重塑AI協作開發的智能體框架實踐指南

一、框架架構與技術突破 1.1 系統架構設計 graph TBA[自然語言需求] --> B(需求解析引擎)B --> C{角色路由系統}C --> D[產品經理Agent]C --> E[架構師Agent]C --> F[工程師Agent]D --> G[PRD文檔]E --> H[架構圖]F --> I[代碼文件]G --> J[知識共…

自用:在使用SpringBoot做學生信息管理系統時遇到的問題

1、在做完查詢測試時&#xff0c;一直報出404找不到錯誤&#xff0c;原因是沒有為各個層的實現類添加注解 2、改完之后發現測試沒有數據&#xff0c;是因為我寫的返回值類型為空&#xff0c;應該返回一個List< Student > 3、我沒有想到要寫Result實體類&#xff0c;因為不…

SQLite + Redis = Redka

Redka 是一個基于 SQLite 實現的 Redis 替代產品&#xff0c;實現了 Redis 的核心功能&#xff0c;并且完全兼容 Redis API。它可以用于輕量級緩存、嵌入式系統、快速原型開發以及需要事務 ACID 特性的鍵值操作等場景。 功能特性 Redka 的主要特點包括&#xff1a; 使用 SQLi…

202529 | RocketMQ 簡介 + 安裝 + 集群搭建 + 消費模式 + 消費者組

RocketMQ簡介 RocketMQ 簡介 Apache RocketMQ 是一款開源的 分布式消息中間件&#xff08;Message Queue, MQ&#xff09;&#xff0c;由阿里巴巴團隊研發并捐贈給 Apache 基金會&#xff0c;現已成為頂級項目。它專為 高吞吐、低延遲、高可靠 的分布式場景設計&#xff0c;廣…

Go語言--語法基礎4--基本數據類型--整數類型

整型是所有編程語言里最基礎的數據類型。 Go 語言支持如下所示的這些整型類型。 需要注意的是&#xff0c; int 和 int32 在 Go 語言里被認為是兩種不同的類型&#xff0c;編譯器也不會幫你自動做類型轉換&#xff0c; 比如以下的例子會有編譯錯誤&#xff1a; var value2 in…

競拍商城:電商創新的博弈場與未來趨勢

競拍商城&#xff1a;電商創新的博弈場與未來趨勢 在傳統電商趨于同質化的今天&#xff0c;競拍商城憑借其獨特的交易機制和用戶激勵模式&#xff0c;成為電商領域的新寵。通過結合拍賣的博弈屬性與電商的便捷性&#xff0c;競拍商城不僅重塑了消費體驗&#xff0c;更催生了全…

Linux : 多線程互斥

目錄 一 前言 二 線程互斥 三 Mutex互斥量 1. 定義一個鎖&#xff08;造鎖&#xff09; 2. 初始化鎖 3. 上鎖 4. 解鎖 5. 摧毀鎖 四 鎖的使用 五 鎖的宏初始化 六 鎖的原理 1.如何看待鎖&#xff1f; 2. 如何理解加鎖和解鎖的本質 七 c封裝互斥鎖 八 可重入…

論文閱讀筆記——Reactive Diffusion Policy

RDP 論文 通過 AR 提供實時觸覺/力反饋&#xff1b;慢速擴散策略&#xff0c;用于預測低頻潛在空間中的高層動作分塊&#xff1b;快速非對稱分詞器實現閉環反饋控制。 ACT、 π 0 \pi_0 π0? 采取了動作分塊&#xff0c;在動作分塊執行期間處于開環狀態&#xff0c;無法及時響…

swagger 注釋說明

一、接口注釋核心字段 在 Go 的路由處理函數&#xff08;Handler&#xff09;上方添加注釋&#xff0c;支持以下常用注解&#xff1a; 注解名稱用途說明示例格式Summary接口簡要描述Summary 創建用戶Description接口詳細說明Description 通過用戶名和郵箱創建新用戶Tags接口分…

STM32 HAL庫 OLED驅動實現

一、概述 1.1 OLED 顯示屏簡介 OLED&#xff08;Organic Light - Emitting Diode&#xff09;即有機發光二極管&#xff0c;與傳統的 LCD 顯示屏相比&#xff0c;OLED 具有自發光、視角廣、響應速度快、對比度高、功耗低等優點。在嵌入式系統中&#xff0c;OLED 顯示屏常被用…

Web開發-JavaEE應用動態接口代理原生反序列化危險Invoke重寫方法利用鏈

知識點&#xff1a; 1、安全開發-JavaEE-動態代理&序列化&反序列化 2、安全開發-JavaEE-readObject&toString方法 一、演示案例-WEB開發-JavaEE-動態代理 動態代理 代理模式Java當中最常用的設計模式之一。其特征是代理類與委托類有同樣的接口&#xff0c;代理類…

K8s是常用命令和解釋

K8s高頻命令 獲取資源信息&#xff0c;如獲取 Pod、Service、Deployment等資源狀態信息 kubectl get創建資源如創建Pod、Service、Deployment等資源 kubectl create刪除資源&#xff0c;如刪除Pod、Service、Deployment等資源 kubectl delete 應用配置文件&#xff0c;如引用D…

【模態分解】EMD-經驗模態分解

算法配置頁面&#xff0c;也可以一鍵導出結果數據 報表自定義繪制 獲取和下載【PHM學習軟件PHM源碼】的方式 獲取方式&#xff1a;Docshttps://jcn362s9p4t8.feishu.cn/wiki/A0NXwPxY3ie1cGkOy08cru6vnvc

TDengine 語言連接器(Go)

簡介 driver-go 是 TDengine 的官方 Go 語言連接器&#xff0c;實現了 Go 語言 database/sql 包的接口。Go 開發人員可以通過它開發存取 TDengine 集群數據的應用軟件。 Go 版本兼容性 支持 Go 1.14 及以上版本。 支持的平臺 原生連接支持的平臺和 TDengine 客戶端驅動支持…