線程池 JMM 內存模型

線程池 & JMM 內存模型

文章目錄

  • 線程池 & JMM 內存模型
  • 線程池
    • 線程池的創建
    • ThreadPoolExecutor 七大參數
    • 飽和策略
    • ExecutorService 提交線程任務對象執行的方法:
    • ExecutorService 關閉線程池的方法:
    • 線程池最大線程數如何確定?
  • volatile - 多線程之間共享變量的可見性
  • JMM 內存模型
    • 八種操作
    • JMM 對這八種指令的使用,制定了如下規則:

線程池

使用線程池可以實現線程的復用,減少頻繁創建和銷毀線程對象造成的資源消耗。

好處

  1. 降低資源消耗:減少了創建和銷毀線程的次數;

  2. 提高響應速度:不需要頻繁的創建線程;

  3. 提高線程的可管理性:線程池可以約束系統中最多的線程數;

線程池的創建

java.util.concurrent.Executors 提供了一系列靜態方法創建線程池對象,線程池在 Java 中表現為 ExecutorService 接口。

  1. 使用 ThreadPoolExecutor 構造方法;

  2. 使用 Executor 框架的?具類 Executors:實際也是調用了 ThreadPoolExecutor 構造方法,阿里巴巴開發手冊強烈不允許使用該種方式

  • FixedThreadPool : 該方法返回?個固定線程數量的線程池。該線程池中的線程數量始終不變。當有?個新的任務提交時,線程池中若有空閑線程,則立即執行。若沒有,則新的任務會被暫存在?個任務隊列中,待有線程空閑時,便處理在任務隊列中的任務。
  • SingleThreadExecutor: 方法返回?個只有?個線程的線程池。若多余?個任務被提交到該線程池,任務會被保存在?個任務隊列中,待線程空閑,按先入先出的順序執?隊列中的任務。
  • CachedThreadPool: 該方法返回?個可根據實際情況調整線程數量的線程池。線程池的線程數量不確定,但若有空閑線程可以復?,則會優先使用可復?的線程。若所有線程均在?作,又有新的任務提交,則會創建新的線程處理任務。所有線程在當前任務執行完畢后,將返回線程池進行復?。

推薦創建線程池方式:ThreadPoolExecutor

ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, // 核心線程數5, // 最大線程數,超出阻塞隊列時才會觸發最大線程數3, // 超出核心線程數時,終止空閑線程的等待時間TimeUnit.SECONDS, // 時間單位new LinkedBlockingQueue<Runnable>(3), // 阻塞隊列Executors.defaultThreadFactory(), // 默認創建線程工廠new ThreadPoolExecutor.AbortPolicy() // 拒絕策略
);

ThreadPoolExecutor 七大參數

  1. corePoolSize:核心線程數,保留在線程池中的線程數,即使它們處于空閑狀態,除非設置了allowCoreThreadTimeOut

  2. maximumPoolSize:最大線程數,當工作隊列中存放的任務達到隊列容量的時候,當前可以同時運行的線程數量變為最?線程數;

  3. keepAliveTime:當線程數大于核心線程數時,這是多余空閑線程在終止前等待新任務的最長時間;

  4. unit:keepAliveTime 參數的時間單位;

  5. workQueue:工作隊列,超出核心線程數的任務會保存在任務隊列, 這個隊列將只保存 execute 方法提交的 Runnable任務;

  6. threadFactory:執行程序創建新線程時使用的工廠;

  7. handler:飽和策略(拒絕策略),執行被阻塞時使用的處理程序,因為達到了線程邊界和隊列容量;

飽和策略

  1. ThreadPoolExecutor.AbortPolicy :拋出 RejectedExecutionException 來拒絕新任務的處理。

  2. ThreadPoolExecutor.CallerRunsPolicy :調用執行自己的線程運行任務(使用提交該任務的線程執行)。您不會任務請求。但是這種策略會降低對于新任務提交速度,影響程序的整體性能。另外,這個策略喜歡增加隊列容量。如果您的應?程序可以承受此延遲并且你不能任務丟棄任何?個任務請求的話,你可以選擇這個策略。

  3. ThreadPoolExecutor.DiscardPolicy : 不處理新任務,直接丟棄掉。

  4. ThreadPoolExecutor.DiscardOldestPolicy : 此策略將丟棄最早的未處理的任務請求。

ExecutorService 提交線程任務對象執行的方法:

  1. Future<?> submit(Runnable task):提交一個 Runnable 的任務對象給線程池執行;

  2. Future<?> submit(Callable task):提交一個 Callable 的任務對象給線程池執行,可以通過 get() 得到返回結果。

  3. public void execute(Runnable command):不返回結果使用 execute;

ExecutorService 關閉線程池的方法:

  1. shutdown():等待任務執行完畢以后才會關閉線程池;

  2. shutdownNow():立即關閉線程池的代碼,無論任務是否執行完畢,相當于給每個線程調用了 intercept() 方法。

線程池提交線程任務對象會自動啟動線程執行。

ExecutorService pools = Executors.newFixedThreadPool(3);// 實現 Callable 接口
Future<String> result= pools.submit((Callable<String>) () -> {});
// 獲取線程執行返回的結果
String r = result.get()// 實現 Runnable 接口
pools.submit(() -> {});

線程池最大線程數如何確定?

  1. CPU 密集型:定義為機器 CPU 核數,Runtime.getRuntime().availableProcessors()

  2. IO 密集型:定義為 IO 密集線程的 2 倍;

線程池主要執行流程

在這里插入圖片描述

volatile - 多線程之間共享變量的可見性

引入:A 線程修改了共享變量的值,但是在主線程中讀取到的還是之前的值,修改后的值無法讀取到。

解釋:根據 JMM 內存模型,線程在本地內存中會有共享變量的副本,A 線程修改了其本地內存的變量更新到主內存中,當主線程操作共享變量時,還是讀取的主線程中本地內存的共享變量副本,此時還沒有跟主內存共享變量同步,導致無法讀取到修改后的值,這個現象稱為線程之間共享變量的不可見性。

解決方案

  1. 加鎖:

? a. 線程獲得鎖;

? b. 清空本地工作內存;

? c. 從主內存中拷貝最新值到工作內存;

  1. 使用 volatile 關鍵字修飾共享變量:使用 volatile 關鍵字修飾的變量被修改后,主內存更新后會將其他線程本地工作內存中的變量副本失效,重新讀取主內存的最新值,從而保證了可見性。

區別:volatile 關鍵字不保證原子性。

volatile 是 Java 虛擬機提供輕量級的同步機制

特點:

  1. 保證可見性

  2. 不保證原子性

  3. 禁止指令重排

JMM 內存模型

在這里插入圖片描述

JMM (Java Memory Model),Java 內存模型。是 Java 虛擬機規范中所定義的一種內存模型。 Java 內存模型(Java Memory Model)描述了 Java 程序中各種變量(線程共享變量)的訪問規則,以及在 JVM 中將變量存儲到內存和從內存中讀取變量這樣的底層細節。 所有的共享變量都存儲于主內存。這里所說的變量指的是實例變量和類變量。不包含局部變量,因為局部變量是線程私有的,因此不存在競爭問題。每一個線程還存在自己的工作內存,線程的工作內存,保留了被線程使用的變量的工作副本。線程對變量的所有的操作(讀,取)都必須在工作內存中完成,而不能直接讀寫主內存中的變量,不同線程之間也不能直接訪問對方工作內存中的變量,線程間變量的值的傳遞需要通過主內存完成。

八種操作

內存交互操作有 8 種,虛擬機實現必須保證每一個操作都是原子的,不可在分的(對于double和long類型的變量來說,load、store、read 和 write 操作在某些平臺上允許例外)

  1. lock (鎖定):作用于主內存的變量,把一個變量標識為線程獨占狀態;

  2. unlock (解鎖):作用于主內存的變量,它把一個處于鎖定狀態的變量釋放出來,釋放后的變量才可以被其他線程鎖定;

  3. read (讀取):作用于主內存變量,它把一個變量的值從主內存傳輸到線程的工作內存中,以便隨后的 load動作使用;

  4. load (載入):作用于工作內存的變量,它把 read 操作從主存中變量放入工作內存中;

  5. use (使用):作用于工作內存中的變量,它把工作內存中的變量傳輸給執行引擎,每當虛擬機遇到一個需要使用到變量的值,就會使用到這個指令;

  6. assign (賦值):作用于工作內存中的變量,它把一個從執行引擎中接受到的值放入工作內存的變量副本中

  7. store (存儲):作用于主內存中的變量,它把一個從工作內存中一個變量的值傳送到主內存中,以便后續的 write 使用

  8. write (寫入):作用于主內存中的變量,它把 store 操作從工作內存中得到的變量的值放入主內存的變量中

JMM 對這八種指令的使用,制定了如下規則:

  1. 不允許 read 和 load、store 和 write 操作之一單獨出現。即使用了read 必須 load,使用了store 必須 write

  2. 不允許線程丟棄他最近的 assign 操作,即工作變量的數據改變了之后,必須告知主存

  3. 不允許一個線程將沒有 assign 的數據從工作內存同步回主內存

  4. 一個新的變量必須在主內存中誕生,不允許工作內存直接使用一個未被初始化的變量。就是懟變量實施 use、store 操作之前,必須經過 assign 和 load 操作

  5. 一個變量同一時間只有一個線程能對其進行 lock。多次 lock 后,必須執行相同次數的 unlock 才能解鎖

  6. 如果對一個變量進行 lock 操作,會清空所有工作內存中此變量的值,在執行引擎使用這個變量前,必須重新load 或 assign 操作初始化變量的值

  7. 如果一個變量沒有被 lock,就不能對其進行 unlock 操作。也不能 unlock 一個被其他線程鎖住的變量

  8. 對一個變量進行 unlock 操作之前,必須把此變量同步回主內存

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

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

相關文章

[論文閱讀] 軟件工程 + 教學 | 軟件工程項目管理課程改革:從傳統教學到以學生為中心的混合式學習實踐

軟件工程項目管理課程改革&#xff1a;從傳統教學到以學生為中心的混合式學習實踐 論文信息 arXiv:2506.14369 Agile and Student-Centred Teaching of Agile/Scrum Concepts Maria Spichkova Comments: Preprint. Accepted to the 29th International Conference on Knowledg…

Windows系統提示“mfc140u.dll丟失”?詳細修復指南,一鍵恢復程序運行!

當你興致勃勃地打開某個游戲或專業軟件時&#xff0c;突然彈出一條錯誤提示——“MFC140u.dll丟失”&#xff0c;程序直接閃退&#xff0c;讓人無比沮喪。別擔心&#xff01;這個問題并不復雜&#xff0c;通常只需重新安裝運行庫或修復系統文件即可解決。本文將為你提供詳細的修…

云XR(AR/VR)算力底座關鍵特征與技術路徑

云XR&#xff08;AR/VR&#xff09;算力底座是支撐擴展現實技術規模化落地的核心基礎設施&#xff0c;當前發展呈現以下關鍵特征與技術路徑&#xff1a; 一、算力架構&#xff1a;云邊端協同異構融合 分布式部署模式? 云端?&#xff1a;承擔高復雜度渲染與大數據處理&#x…

Android開發常用adb合集

Android開發常用adb合集 Android開發常用adb合集crash日志導出 Android開發常用adb合集 crash日志導出 bugreport: adb bugreportdropbox: adb shell dumpsys dropbox --print > desktop/full_dropbox_logs.txt

LTspice仿真4——exp指數函數波形

參數設置 Vinitial&#xff1a;初始電壓值 Vpulsed&#xff1a;脈沖達到值 Rise Delay&#xff1a;上升延遲時間 Rise Tau&#xff1a;上升指數系數tau Fall Delay&#xff1a;下降延遲時間 Fall Tau&#xff1a;下降指數系數tau tau決定指數波形下降或者上升快慢&#x…

[Java 基礎]集合框架

在 Java 中&#xff0c;我們經常需要存儲和操作一組數據&#xff0c;而集合框架就是為此而生。它提供了一套統一的接口和類&#xff0c;幫助我們高效地管理各種數據集合。 常用的集合框架中的類只有 ArrayList、LinkedList、HashSet、HashMap 這 4 個&#xff0c;這些類的繼承…

SQL關鍵字三分鐘入門:WITH —— 公用表表達式讓復雜查詢更清晰

在實際的數據庫開發和分析中&#xff0c;我們常常會遇到復雜的多層嵌套查詢&#xff0c;這樣的 SQL 語句不僅難以閱讀&#xff0c;也容易出錯。 這時候就需要使用一個非常實用又優雅的關鍵字 —— WITH&#xff01; 它可以幫助我們將復雜的子查詢提取出來并命名&#xff0c;從…

要在 Linux 不聯網服務器 上部署并運行 Gitee 上的 vue-vben-admin 項目,并且該項目使用的是 pnpm 管理依賴

目錄 ? 目標&#xff1a;在不聯網服務器中成功運行 vue-vben-admin &#x1f449; 你需要的最終環境&#xff1a; ? 場景&#xff1a;完全離線部署并運行開發/構建環境 &#x1f9f1; 步驟總覽&#xff1a; &#x1f6e0; 詳細操作流程 ? 第 1 步&#xff1a;聯網機器準…

中國風國潮通用PPT模版

中國風答辯總結匯報類通用PPT模版&#xff0c;古風PPT通用模版&#xff0c;國學精品PPT模版&#xff0c;中國風韻PPT模版 中國風國潮通用PPT模版&#xff1a;https://pan.quark.cn/s/59cea717fe8d

【nvidia-H100-ib排障實戰2】:服務器 InfiniBand 網絡性能問題深度分析

目錄 InfiniBand 網絡性能日志: 實際生產服務器 InfiniBand 網絡性能問題深度分析 一、核心問題定位:mlx5_1 設備性能異常 二、問題詳細分析 1. mlx5_1 設備異常原因推測 (1)硬件連接故障 (2)驅動或固件問題 (3)資源爭用或配置錯誤 2. CPU 頻率不一致問題 三…

Postgresql中不同數據類型的長度限制

目錄 一、字符類型&#xff08;Character Types&#xff09; 二、二進制類型&#xff08;Binary Types&#xff09; 三、數值類型&#xff08;Numeric Types&#xff09; 四、其他類型 五、全局限制&#xff1a;單行數據總大小 示例對比表 注意事項 驗證命令 在 Postgr…

Unity Hub 新建項目,啟動 Unity 閃退的解決辦法

問題&#xff1a; Win11: Unity 閃退&#xff0c;提示 Could not connect project 原因 這是 Firewall & network protection 在作怪&#xff0c;真的我感覺 Windows Defender 就從來沒干過好事&#xff0c;那個遍地是病毒的年代微軟你不搞個殺毒軟件&#xff0c;現在…

學習打卡---回溯

回溯&#xff0c;所有回溯都可以轉換成樹形結構進行解決 我們將樹形結構分為縱向和橫向兩個方面 遞歸是縱向循環&#xff0c;也就是縱向方面&#xff0c;到了葉子節點就收網回溯 循環是橫向循環&#xff0c;也就是橫向方面&#xff0c;到了數組末尾就結束 回溯屬于是將二叉樹的…

阿里云獲取DASHSCOPE_API_KEY教程,以及配置DASHSCOPE_API_KEY環境變量

要獲取阿里云的 DASHSCOPE_API_KEY&#xff08;通義千問API密鑰&#xff09;&#xff0c;需要在阿里云平臺上完成開通服務和創建密鑰的流程。以下是具體步驟&#xff1a; 1. 開通通義千問API服務 登錄阿里云賬號 訪問 阿里云官網&#xff0c;使用賬號密碼或RAM用戶登錄。 進入…

《去哪兒網Redis高并發實戰:從問題定位到架構升級》

去哪兒網Redis高并發實戰&#xff1a;從問題定位到架構升級 在互聯網行業競爭日益激烈的當下&#xff0c;高并發場景下的系統性能優化一直是技術團隊面臨的重要挑戰。對于去哪兒網這類在線旅游平臺來說&#xff0c;節假日期間的流量高峰更是對系統架構的嚴峻考驗。本文將深入剖…

Zynq + FreeRTOS + YAFFS2 + SQLite3 集成指南

Zynq FreeRTOS YAFFS2 SQLite3 集成指南 一、系統架構設計 #mermaid-svg-qvuP6slyza89wsiT {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-qvuP6slyza89wsiT .error-icon{fill:#552222;}#mermaid-svg-qvuP6slyz…

設計模式精講 Day 6:適配器模式(Adapter Pattern)

【設計模式精講 Day 6】適配器模式&#xff08;Adapter Pattern&#xff09; 文章內容 在“設計模式精講”系列的第6天&#xff0c;我們將深入講解適配器模式&#xff08;Adapter Pattern&#xff09;。作為結構型設計模式之一&#xff0c;適配器模式的核心思想是將一個類的接…

系統穩定性治理

一、微服務內部異常 描述 微服務Pod自動重啟表現&#xff1a;服務波動&#xff08;響應時間不穩定&#xff09;、監控指標異常&#xff08;Pod重啟次數增加&#xff0c;CPU/內存波動&#xff09;、Kubernetes事件記錄容器重啟原因影響&#xff1a;服務中斷、性能波動、資源消耗…

多智能體協同的力量:賦能AI安全報告系統的智能設計之道

“設想一個由‘數據采集者’、‘風險分析師’、‘報告撰寫員’甚至‘合規監督員’組成的虛擬團隊&#xff0c;它們如何攜手打造一份深度洞察、精準預警的危化安全報告&#xff1f;這正是多智能體協作在AI安全領域的魅力所在。” 一、挑戰升級&#xff1a;單一AI難以應對的復雜性…

ceph pg 卡在 active+clean+remapped 狀態

場景 ceph 環境中有個 osd.0 做了 raid0 ,后來想剔除掉,執行了 ceph osd out 0 然后等了很長時間等 pg 數據遷移到別的 osd,但是最后有一個 pg 狀態卡在了 active+clean+remapped 狀態。如下: ceph pg ls-by-osd 0 PG OBJECTS DEGRADED MISPLACED UNFOUND BYTES …