java多線程——線程池

概述

線程池是管理java線程生命周期的工具

  • 降低資源消耗。通過池化技術能夠重復利用已創建的線程,降低線程頻繁創建和銷毀造成的資源消耗
  • 提高線程的可管理性。無需程序員手動銷毀線程,控制線程創建的數量,避免無限制的創建影響系統穩定性

線程池的運行機制

線程池的核心參數

  1. corePoolSize(必需):核心線程數量。默認情況下,核心線程會一直存活,但是當allowCoreThreadTimeout 設置為true時,核心線程也會超時回收
  2. maximumPoolSize(必需):最大線程數量,當線程池內的線程數量到達該數之后,后續的新任務將交由拒絕策略處理
  3. keepAliveTime(必需):線程閑置超時時長。如果閑置線程的時間超過該時長,非核心線程就會被回收,如果allowCoreThreadTimeout 設置為true時,核心線程也會超時回收
  4. unit(必需):keepAliveTime參數的時間單位
  5. workQueue(必需):線程等待隊列即任務等待的隊列
  6. threadFactory(可選):線程工廠,用于指定線程池創建新線程的方式
  7. handler(可選):拒絕策略,當到達最大線程數時需要執行的拒絕策略, 默認為AbortPolicy即丟棄任務并拋異常

提交任務的流程

線程池實現類——ThreadPoolExecutor

構造方法

參數說明

ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue)

corePoolSize:核心線程池大小

maximumPoolSize:最大線程池大小

keepAliveTime:當線程數>核心線程數時,這是 多余線程在任務執行完成后最大的存活時間

unit:時間單位

workQueue:線程等待隊列即任務等待的隊列

ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue,

ThreadFactory threadFactory)

corePoolSize:核心線程池大小

maximumPoolSize:最大線程池大小

keepAliveTime:當線程數>核心線程數時,這是 多余線程在任務執行完成后最大的存活時間

unit:時間單位

workQueue:線程等待隊列即任務等待的隊列

threadFactory:線程創建工廠

ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue,

RejectedExecutionHandler handler)

corePoolSize:核心線程池大小

maximumPoolSize:最大線程池大小

keepAliveTime:當線程數>核心線程數時,這是 多余線程在任務執行完成后最大的存活時間

unit:時間單位

workQueue:線程等待隊列即任務等待的隊列

handler:拒絕執行某個線程的策略LinkedBlockingQueue

LinkedBlockingQueue<Runnable>

隊列默認size=Integer.MAX_VALUE,即是一個無界隊列

底層實現是鏈表;讀和寫使用的是兩個不同的鎖,所以是讀寫分離的隊列。

阻塞操作:

take();//當隊列中無元素時,阻塞等待

put();//當隊滿時阻塞等待

非阻塞操作:

poll();//當隊列為null時,返回null

offer();//堆滿時return false;

功能線程池

Executors已經為我們封裝好了四種常見的功能線程池:

  • 定長線程池(FixedThreadPool)
  • 定時線程池(ScheduledThreadPool )
  • 可緩存線程池(CachedThreadPool)
  • 單線程化線程池(SingleThreadExecutor)

從結構圖中能看到四種線程池的真正實現類是ThreadPoolExecutor

線程池類型

1、newScheduledThreadPool 調度型線程池

  • 支持定時及周期性的執行任務,提交任務時支持設置任務的調度周期
  • 只限制了核心線程數,也就是最大線程數為Integer.MAX_VALUE,當添加任務的速度大于線程池處理任務的速度,可能會創建大量的線程,消耗資源,甚至導致OOM

1.1 構造

構造方法

參數

newScheduledThreadPool(int corePoolSize)

corePoolSize:corePoolSize

maximumPoolSize:Integer.MAX_VALUE

keepAliveTime:0

unit:NANOSECONDS

workQueue:DelayedWorkQueue

newScheduledThreadPool( int corePoolSize, ThreadFactory threadFactory)

1.2 任務隊列-DelayedWorkQueue

  • 該隊列的數據結構是優先級隊列(依賴堆實現),當新來任務時將該task插入堆并根據優先級重新調整堆,保證優先級最高的task在fist index
  • 執行任務時,獲取fist index中的task,并保證等待夠delay時間后再執行(當fist task執行后也需要重新調整堆)

2、newCachedThreadPool 緩存型線程池

  • 無核心線程數,無非核心線程數,執行完閑置60s回收,任務隊列為不存儲元素的阻塞隊列
  • 適用于短期異步的小任務,或負載較輕的服務器
  • 創建的最大線程數為Integer.MAX_VALUE,當添加任務的速度大于線程池處理任務的速度,可能會創建大量的線程,消耗資源,甚至導致OOM

2.1 構造方法

構造方法

參數

ExecutorService newCachedThreadPool()

參數默認值

corePoolSize:0

maximumPoolSize:Integer.MAX_VALUE

keepAliveTime:60L

unit:TimeUnit.SECONDS

workQueue:SynchronousQueue<Runnable>

ExecutorService newCachedThreadPool(ThreadFactory threadFactory)

2.2 任務隊列-SynchronousQueue

  • 隊列是不存儲元素緩存隊列的,每次要進行offer操作時必須等待poll操作,否則不能繼續添加元素
  • 當前線程A執行offer操作將task添加到queue中,若沒有另一個線程來消費該task,那線程A會一直阻塞直到另一個線程來消費該task

3、newFixedThreadPool

  • 創建固定大小的線程池。每次提交一個任務就創建一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,如果某個線程因為執行異常而結束,那么線程池會補充一個新線程
  • 適用于限制當前線程數量的應用場景,適用于負載比較重的服務器
  • 創建了一個無界隊列LinkedBlockingQueuesize,是一個最大值為Integer.MAX_VALUE的線程阻塞隊列,當添加任務的速度大于線程池處理任務的速度,可能會在隊列堆積大量的請求,消耗很大的內存,甚至導致OOM

3.1 構造方法

構造方法

參數

ExecutorService newFixedThreadPool(int nThreads)

corePoolSize:nThreads

maximumPoolSize:nThreads

keepAliveTime:0L

unit:TimeUnit.MILLISECONDS,

workQueue:LinkedBlockingQueue<Runnable>

threadFactory

ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory)

3.2 任務隊列-LinkedBlockingQueue<Runnable>

  • 隊列默認size=Integer.MAX_VALUE即是一個無界隊列,底層實現是鏈表,當添加任務的速度大于線程池處理任務的速度,可能會在隊列堆積大量的請求,消耗很大的內存,甚至導致OOM
  • 讀和寫使用的是兩個不同的鎖,所以是讀寫分離的隊列

4、SingleThreadExecutor

  • 創建一個單線程的線程池。這個線程池只有一個線程在工作,也就是相當于單線程串行執行所有任務,如果這個唯一的線程因為異常結束,那么會有一個新的線程來替代它
  • 此線程池保證所有任務的執行順序按照任務的提交順序執行

4.1 構造方法

構造方法

參數

ExecutorService newSingleThreadExecutor()

corePoolSize:1

maximumPoolSize:1

keepAliveTime:0L

unit:TimeUnit.MILLISECONDS,

workQueue:LinkedBlockingQueue<Runnable>

threadFactory

ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory)

4.2 任務隊列-LinkedBlockingQueue<Runnable>

  • 隊列默認size=Integer.MAX_VALUE即是一個無界隊列,底層實現是鏈表,當添加任務的速度大于線程池處理任務的速度,可能會在隊列堆積大量的請求,消耗很大的內存,甚至導致OOM
  • 讀和寫使用的是兩個不同的鎖,所以是讀寫分離的隊列

線程池拒絕策略:

實現java.util.concurrent.RejectedExecutionHandler接口

1,CallerRunsPolicy:當想提交任務的線程池還存活,就由提交task的當前線程來執行

2,AbortPolicy:丟棄任務并拋出RejectedExecutionException異常,(默認拒絕策略)

3,DiscardPolicy:丟棄任務但是不拋異常

4,DiscardOldestPolicy:當想提交任務的線程池還存活,就將丟棄隊列最前面的任務,然后重新提交被拒絕的任務

對比

類型

池內線程數量

任務隊列

特點

應用場景

newScheduledThreadPool

核心線程:固定

非核心線程:無限制

DelayedWorkQueue

  1. 定時,周期性執行

執行定時/周期性任務

newCachedThreadPool

無限制

SynchronousQueue

  1. 無最大線程數限制
  2. 隊列不存儲元素,當沒有空閑線程時會立即新建線程
  3. 當添加任務的速度大于線程池處理任務的速度,可能會創建大量的線程,消耗資源,甚至導致OOM

執行數量多,耗時少的線程任務

newFixedThreadPool

固定

LinkedBlockingQueue

  1. 每來一個任務就會新建線程,直到線程數到達指定的數量
  2. 核心線程數處于空閑狀態也不會被回收,除非線程關閉
  3. 當所有線程都處于活躍狀態,新的任務都會處于等待狀態,直到有線程空閑出來
  4. 任務隊列無限制

控制線程的最大并發數

newSingleThreadExecutor

1個

LinkedBlockingQueue

  1. 保證所有任務按照指定順序在一個線程中方執行
  2. 不需要處理線程同步的問題

單線程

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

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

相關文章

找不到kotlin.Pair的類文件

需要添加kotlin的依賴&#xff1a; implementation "org.jetbrains.kotlin:kotlin-stdlib:1.8.22"

OpenHarmony上移植memtester

1. 下載源碼&#xff1a; wget https://pyropus.ca./software/memtester/old-versions/memtester-4.6.0.tar.gz 2. 解壓并指定交叉編譯方式 解壓 tar -xvf memtester-4.6.0.tar.gz 修改conf-cc和conf-ld&#xff0c;指定交叉編譯方式 conf-cc conf-ld 3. 編譯 直接運行m…

Ubuntu安裝ZLMediaKit

方式一 1、安裝vcpkg 在Ubuntu上安裝vcpkg的步驟如下&#xff1a; 安裝必要的依賴&#xff1a; 首先&#xff0c;你可能需要安裝cmake和ninja-build。你可以使用apt包管理器來安裝它們&#xff1a; bash復制代碼sudo apt install cmake ninja-build下載vcpkg源碼&#xff1a;…

后端開發面經系列 -- 阿里C++二面面經

阿里C二面面經 公眾號&#xff1a;阿Q技術站 來源&#xff1a;https://www.nowcoder.com/feed/main/detail/fc4a48403b534aafa6a6bce14b542c4e?sourceSSRsearch 1、智能指針&#xff1f; std::shared_ptr&#xff1a; 原理&#xff1a;std::shared_ptr是基于引用計數的智能指…

Stable Diffusion入門使用技巧及個人實例分享--大模型及lora篇

大家好&#xff0c;近期使用Stable Diffusion比較多&#xff0c;積累整理了一些內容&#xff0c;得空分享給大家。如果你近期正好在關注AI繪畫領域&#xff0c;可以看看哦。 本文比較適合已經解決了安裝問題&#xff0c;&#xff08;沒有安裝的在文末領取&#xff09; 在尋找合…

【RAG】Linux系統下ppt轉pptx,讀取解析pptx文本數據

前情提要 檢索增強生成&#xff08;RAG&#xff09;技術&#xff0c;作為 AI 領域的尖端技術&#xff0c;能夠提供可靠且最新的外部知識&#xff0c;極大地便利了各種任務。在 AI 內容生成的浪潮中&#xff0c;RAG 通過其強大的檢索能力為生成式 AI 提供了額外的知識&#xff…

vue3 動態加載頁面

首先&#xff0c;通過下面代碼告訴編譯器要編譯哪些頁面 static modules import.meta.glob(./views/**/*.vue);然后動態加載函數這樣寫&#xff1a; static asyncLoadView (path: string) > {return defineAsyncComponent({loader: <any>Global.modules[./views/${…

Redis的跳表:高效實現有序集合

在 Redis 中&#xff0c;跳表&#xff08;Skip List&#xff09;是一種常用的數據結構&#xff0c;用于實現有序集合&#xff08;Sorted Set&#xff09;。跳表是一種基于鏈表的數據結構&#xff0c;具有快速的查找、插入和刪除操作&#xff0c;適用于有序集合的實現。 本文將…

分布式搜索——ElasticSeach簡介

一般都用數據庫存儲數據&#xff0c;然后對數據庫進行查詢獲取數據&#xff0c;但是當數據量很大時&#xff0c;查詢效率就會很慢&#xff08;具體下面會講到&#xff09;&#xff0c;所以這種情況下就會使用到ElasticSeach ElasticSeach的基本介紹 ElasticSeach是一 款非常強…

2024重慶高等教育博覽會|2024重慶高教展|全國高等教育博覽會

2024重慶高等教育博覽會|2024重慶高教展|全國高等教育博覽會 第62屆全國高等教育博覽會&#xff08;2024.秋季重慶&#xff09; 時間&#xff1a;2024年11月15-17日 地點&#xff1a;重慶國際博覽中心 組織機構 主辦單位&#xff1a;中國高等教育學會 承辦單位&#xff1a;國藥…

杰發科技AC7801——ADC之Bandgap和內部溫度計算

0. 參考 電流模架構Bandgap設計與仿真 bandgap的理解&#xff08;內部帶隙電壓基準&#xff09; ? ? 雖然看不懂這些公式&#xff0c;但是比較重要的一句應該是這個&#xff1a;因為傳統帶隙基準的輸出值為1.2V ? 1. 使用 參考示例代碼。 40002000是falsh控制器寄…

NXP RT1176(一)——二級BootLoader開發(安全引導加載程序SBL)

目錄 1. 開發環境 2. 二級BOOT的功能 3. 步驟 3.1 配置源碼 3.2 構建項目 3.2.1 MDK 3.2.2 IAR&#xff08;IAR也編譯一下工程看看&#xff0c;這樣兩個平臺都可以支持了&#xff09; 單核M7的開發&#xff01;&#xff01; 1. 開發環境 本文Windows下開發&#xff1a;…

【無標題】vo dto

在Java中&#xff0c;VO、PO、DTO都是常用的數據對象模型。 VO&#xff08;Value Object&#xff09;是值對象&#xff0c;通常用于表示一個業務實體或者頁面展示的內容。VO通常包含了多個屬性&#xff0c;并且這些屬性的類型和名稱與業務相關。VO并不一定與數據庫中的表結構相…

MHD、MQA、GQA注意力機制詳解

MHD、MQA、GQA注意力機制詳解 注意力機制詳解及代碼前言&#xff1a;MHAMQAGQA 注意力機制詳解及代碼 前言&#xff1a; 自回歸解碼器推理是 Transformer 模型的 一個嚴重瓶頸&#xff0c;因為在每個解碼步驟中加 載解碼器權重以及所有注意鍵和值會產生 內存帶寬開銷 下圖為三…

鞏固學習8

在 Pandas 中&#xff0c;sep參數用于指定數據中字段之間的分隔符。常見的參數包括&#xff1a; 逗號&#xff1a;,&#xff0c;常用于CSV文件。 制表符&#xff1a;\t&#xff0c;常用于TSV文件。 空格&#xff1a;’ &#xff0c;用于空格分隔的數據。 分號&#xff1a;;&…

【合成孔徑雷達】合成孔徑雷達的多視角理解和時/頻成像算法的統一解釋

文章目錄 一、什么是雷達成像&#xff08;1&#xff09;主要的遙感探測手段&#xff1a;光學、紅外和雷達&#xff08;2&#xff09;從數學的角度&#xff1a;雷達成像主要研究什么&#xff1f;數據采集&#xff1a; y T x n yTxn yTxn信息提取&#xff1a; y ? > x ? y…

編譯錯誤:stray ‘\357’ in program的解決方法

目錄 把報錯文件更換編碼格式&#xff0c;我試的utf-8 bom編碼就可以了&#xff0c;可以多換幾種試試。 網友的另一種案例&#xff1a; 編譯錯誤&#xff1a;stray ‘\357’ in program的解決方法 把報錯文件更換編碼格式&#xff0c;我試的utf-8 bom編碼就可以了&#xff0c…

LabVIEW做儀器測試不知道是否適用

LabVIEW&#xff08;Laboratory Virtual Instrument Engineering Workbench&#xff09;是一個用于系統工程和測量系統的圖形編程平臺&#xff0c;由National Instruments開發。它非常適用于儀器控制、數據采集、信號處理以及自動化測試與測量系統的開發。如果您的工作涉及到這…

如何同步管理1000個設備的VLAN數據?

什么是VLAN&#xff1f; VLAN&#xff0c;也就是虛擬局域網&#xff0c;是通過為子網提供數據鏈路連接來抽象出局域網的概念。在企業網中&#xff0c;一個企業級交換機一般是24口或者是48口&#xff0c;連接這些接口的終端在物理上形成一個廣播域。廣播域過大&#xff0c;就會導…

【AI智能體】零代碼構建AI應用,全網都在喊話歌手誰能應戰,一鍵AI制作歌手信息查詢應用

歡迎來到《小5講堂》 這是《文心智能體平臺》系列文章&#xff0c;每篇文章將以博主理解的角度展開講解。 溫馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不對之處望指正&#xff01; 目錄 文心智能體大賽背景創建應用平臺地址快速構建【基礎配置】…