[從零開始學習JAVA ] 了解線程池

前言:

????????在Java編程中,線程池是一個強大的工具,它能夠管理和復用線程,提供高效的并發處理能力。通過線程池,我們可以有效地控制并發線程的數量,并降低線程創建和銷毀的開銷。本文將引導你深入了解Java中的線程池,探索其原理、用法和優勢,為你提供一個更高效的編程方式。

?線程池的作用就是管理線程數量,減少線程頻繁的創建和銷毀?

?線程池:

???線程池是一種用于管理和復用線程的技術,它可以有效地處理并發任務并提高程序的性能和響應能力。線程池維護著一個線程隊列,其中包含了一定數量的線程。當有新的任務到達時,線程池會從隊列中選擇一個空閑的線程來執行任務,而不是為每個任務都創建新的線程。?

線程池的工作流程:

  • 創建線程池,包括初始化線程隊列和創建指定數量的線程。
  • 將任務提交給線程池。可以通過將任務對象提交給線程池的方式來添加新的任務。
  • 線程池從任務隊列中選擇一個空閑的線程來執行任務。
  • 執行任務。線程池中的線程會執行任務對象中定義的操作。
  • 任務執行完成后,線程返回線程池并等待下一個任務。
  • 線程池繼續從任務隊列中選擇新的任務并分配給空閑線程,循環執行以上步驟

代碼實現線程池:

1.創建線程池的工具類? ?ExecutorService:

  • public static ExecutorService newCachedThreadPool() ? ?創建一個沒有上限的線程池
  • public static ExecutorService newCachedThreadPool(int int nthread) ? ?創建一個有上限的線程池

?其實第一個創建線程池不是真正沒有上限,他的上限是int的最大范圍,只不過因為實在是太大了,因此我們說沒有上限。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolExample {public static void main(String[] args) {// 創建一個固定大小為5的線程池ExecutorService threadPool = Executors.newFixedThreadPool(5);// 提交任務給線程池for (int i = 0; i < 10; i++) {final int taskId = i;threadPool.execute(new Runnable() {public void run() {try {System.out.println("開始執行任務:" + taskId);Thread.sleep(2000); // 模擬任務執行時間System.out.println("任務執行完成:" + taskId);} catch (InterruptedException e) {e.printStackTrace();}}});}// 關閉線程池threadPool.shutdown();}
}

?小技巧:

通過打斷點的方式,我們可以實時看到當前線程池中的線程數量:

?

2.自定義創建線程池對象 ?ThreadPoolExecutor:

在Java中,我們可以使用ThreadPoolExecutor來自定義創建線程池對象。ThreadPoolExecutor是ExecutorService接口的一個實現類,它允許我們靈活地配置線程池的核心線程數、最大線程數、線程存活時間等參數。
首先,我們需要導入java.util.concurrent包。然后,可以通過以下代碼創建一個自定義的線程池對象

public class test03 {public static void main(String[] args) {ThreadPoolExecutor pool = new ThreadPoolExecutor(3,//核心線程數量6,//最大線程數60,//空閑線程最大存活時間TimeUnit.SECONDS,//時間單位new ArrayBlockingQueue<>(3),//指定任務隊列最大長度Executors.defaultThreadFactory(),//創建線程工廠new ThreadPoolExecutor.AbortPolicy()//任務的拒絕策略);}
}

在上述代碼中,我們傳入了核心線程數、最大線程數、非核心線程空閑超時時間以及任務隊列等參數來創建線程池對象。你還可以根據需要,調整這些參數以滿足你的實際需求。

  • 核心線程數(corePoolSize):核心線程數是線程池中一直存活的線程數量。當提交一個任務時,如果當前核心線程數還未達到設定的值,線程池會創建新的核心線程來處理任務。即使核心線程處于空閑狀態,它們也不會被回收。
  • 最大線程數(maxPoolSize):最大線程數是線程池中能容納的最大線程數量。當提交的任務超過了核心線程數并且任務隊列已滿時,線程池會創建新的線程來執行任務,直到達到最大線程數。超過最大線程數的任務將會被拒絕執行。
  • 非核心線程空閑超時時間(keepAliveTime):當線程池中的線程數量超過核心線程數,并且這些線程處于空閑狀態時,非核心線程會被回收。空閑超時時間設定了非核心線程的最長存活時間,超過這個時間,空閑的非核心線程將被回收。

任務拒絕策略

在Java中,任務拒絕策略用于處理線程池無法接受更多任務時的行為。當線程池已滿并且工作隊列已滿或達到最大容量時,新提交的任務可能會被拒絕執行。Java提供了四種默認的任務拒絕策略:

  1. AbortPolicy(中止策略):這是默認的任務拒絕策略。當線程池無法接受新任務時,新提交的任務會立即拋出RejectedExecutionException異常。
  2. CallerRunsPolicy(調用者運行策略):如果線程池無法接受新任務,則由提交任務的線程來執行該任務。這意味著任務的執行將回退到調用線程中執行,從而降低了整體的并發度。
  3. DiscardPolicy(丟棄策略):當線程池無法接受新任務時,新提交的任務將被靜默丟棄,不會拋出任何異常。這意味著被丟棄的任務將不會被執行。
  4. DiscardOldestPolicy(丟棄最舊策略):當線程池無法接受新任務時,線程池會丟棄工作隊列中最舊的任務(即最先提交的任務),然后嘗試再次提交新任務。

除了這四種默認的拒絕策略外,還可以通過實現RejectedExecutionHandler接口來自定義任務拒絕策略。通過實現該接口,可以定義自己的拒絕策略邏輯,例如將被拒絕的任務記錄下來或將其放入其他隊列中等。然后,可以將自定義的拒絕策略傳遞給線程

在自定義線程池中,我們需要掌握好自定義過程中的七個參數的意義。

線程池多大才算合適?

線程池大小的計算是有計算公式的,在介紹計算公式之前,我們要先講解一下什么是最大并行數

最大并行數指的是在給定的系統環境下同時執行的最大線程或任務數。

線程池大小計算公式:?

1.CPU密集型運算
????????在CPU密集型運算中,任務主要是由CPU執行,涉及較少的I/O操作。在這種情況下,線程池的大小可以通過以下公式計算:

最大并行數+1

2.I/O密集型運算:

????????在I/O密集型運算中,任務涉及大量的I/O操作,例如讀取文件、網絡通信等。在這種情況下,由于任務執行時間中有很多時間被阻塞在I/O等待上,可以通過以下公式計算線程池的大小:

Nthreads = Ncpu * Ucpu * (1 + (W/C))
?

Nthreads 是線程池中的線程數。
Ncpu 是計算機中的CPU核心數。
Ucpu 是期望的CPU利用率(0 <= Ucpu <= 1)。它表示期望的CPU工作時間與總時間的比例。
W/C 通常設置為較大的值,以便在I/O等待期間可以讓CPU執行其他任務。
在I/O密集型任務中,通過增加線程池的大小可以更好地利用I/O等待的時間,提高整體的并發性能。然而,過量的線程數也會增加上下文切換的開銷,因此需要根據實際創建

?

?

?

?


?

?

?

?

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

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

相關文章

Nginx — Nginx處理Web請求機制解析

一、Nginx請求默認頁面資源 1、配置文件詳解 修改端口號為8080并重啟服務&#xff1a; 二、Nginx進程模型 1、nginx常用命令解析 master進程&#xff1a;主進程&#xff08;只有一個&#xff09; worker進程&#xff1a;工作進程&#xff08;可以有多個&#xff0c;默認只有一…

【C++標準IO庫】字符串流

目錄 一、字符串流概述 1.1 流的概念回顧 1.2 字符串流的定義和作用 二、istringstream 的使用 2.1 基本用法 2.2 常見應用場景 三、ostringstream 的使用 3.1 基本用法 3.2 常見應用場景 四、stringstream 的使用 4.1 基本用法 4.2 常見應用場景 五、字符串流的錯…

C語言pthread庫的線程休眠和喚醒的案例

一、代碼如下 #include<stdio.h> #include<pthread.h> // 定義獨占鎖 pthread_mutex_t mutex; // 定義條件信號對象 pthread_cond_t condition; // 初始化函數 void init(){ int code pthread_mutex_init(&mutex, NULL); printf("共享鎖初…

人臉照片比對 API 接口如何對接?

隨著數字化程度加深&#xff0c;身份驗證的重要性也日益凸顯&#xff0c;它成為保障個人信息安全、維護交易秩序的關鍵環節。人臉照片比對 API 接口作為連接人臉比對技術與各類應用的橋梁&#xff0c;正發揮著越來越重要的作用&#xff0c;成為眾多企業和開發者實現高效、安全身…

java學習筆記9——常用類

字符串相關的類&#xff1a; String 指向同一個地址可才相等 注意這個地方&#xff0c;兩個person對象的name實際上指向的是同一個字符串常量池&#xff08;Tom&#xff09; String常用方法 總結&#xff1a; 1.string類的理解(以JDK8為例說明) 1.1 類的聲明 public final cl…

Day 09

文章目錄 指針數組指針和函數技術名詞解釋技術細節課堂筆記 指針數組 #include<stdio.h> int main() {int a[3] {0,1,2};//指針數組&#xff0c;它是數組&#xff0c;每個元素都是指針int *p[3];p[0] &a[0];p[0] a;p[1] &a[1];p[1] a1;p[2] &a[2];p[…

Nginx — Nginx安裝證書模塊(配置HTTPS和TCPS)

一、安裝和編譯證書模塊 [rootmaster nginx]# wget https://nginx.org/download/nginx-1.25.3.tar.gz [rootmaster nginx]# tar -zxvf nginx-1.25.3.tar.gz [rootmaster nginx]# cd nginx-1.25.3 [rootmaster nginx]# ./configure --prefix/usr/local/nginx --with-http_stub_…

計算機網絡 用deepseek幫助整理的復習資料(一)

### 計算機網絡基礎知識整理 --- #### **一、網絡類型** 1. **局域網 (LAN)** - **定義**&#xff1a;覆蓋小范圍&#xff08;如家庭、教室、公司&#xff09;。 - **特點**&#xff1a;高帶寬、低延遲&#xff0c;設備通過交換機互聯。 - **示例**&#xff1…

Linux SCP傳輸文件免密配置

文章目錄 Linux SCP傳輸文件免密配置生成SSH密鑰對將公鑰復制到遠程服務器測試SSH連接使用SCP免密傳輸文件可選配置帶密碼的秘鑰連接處理使用 ssh-agent進行緩存管理&#xff08;該方式只能確保同一個回話中&#xff0c;多次傳輸只輸一次密碼&#xff09;使用 keychain&#xf…

數字電子技術基礎(三十六)——利用Multisim軟件實現3線-8線譯碼器

目錄 1 手動方式實現3線-8線譯碼器 2 使用字選擇器實現3線-8線譯碼器 現在嘗試利用Multisim軟件來實現3線-8線譯碼器。本實驗目的是驗證74LS138的基本功能&#xff0c;簡單來說就是“N中選1”。 實驗設計&#xff1a; &#xff08;1&#xff09;使能信號&#xff1a;時&am…

wait和notify : 避免線程餓死(以及votile內存可見性和指令重排序問題)

各位看官&#xff0c;大家早安午安晚安呀~~~ 如果您覺得這篇文章對您有幫助的話 歡迎您一鍵三連&#xff0c;小編盡全力做到更好 歡迎您分享給更多人哦 今天我們來學習&#xff1a;wait和notify : 避免線程餓死&#xff08;以及votile內存可見性和指令重排序問題&#xff09; …

HarmonyOS 介紹

HarmonyOS簡介 隨著萬物互聯時代的開啟&#xff0c;應用的設備底座將從幾十億手機擴展到數百億IoT設備。全新的全場景設備體驗&#xff0c;正深入改變消費者的使用習慣。 同時應用開發者也面臨設備底座從手機單設備到全場景多設備的轉變&#xff0c;全場景多設備的全新底座&am…

【視覺提示學習】3.28閱讀隨想

2109.01134 CoOp通過可學習的向量來建模提示的上下文詞匯&#xff0c;這些向量可以用隨機值或預訓練的詞嵌入進行初始化&#xff08;見圖2&#xff09;。我們提供了兩種實現方式&#xff0c;以處理不同性質的任務&#xff1a;一種是基于統一上下文&#xff08;unified context…

計算機求職面試中高頻出現的經典題目分類整理

以下為計算機求職面試中高頻出現的經典題目分類整理&#xff0c;涵蓋技術核心與深度考察方向&#xff0c;答案要點已附解析思路&#xff1a; 一、數據結構與算法 鏈表操作 題目&#xff1a;反轉鏈表&#xff08;迭代/遞歸實現&#xff09;考察點&#xff1a;指針操作、遞歸思維…

uniapp選擇文件使用formData格式提交數據

1. Vue實現 在vue項目中,我們有個文件,和一些其他字段數據需要提交的時候,我們都是使用axios 設置請求頭中的Content-Type: multipart/form-data,然后new FormData的方式來進行提交。方式如下: const sendRequest = () => {const formData = new FormData()formData…

BeanDefinition和Beanfactory實現一個簡單的bean容器

目錄 什么是 Springbean 容器 設計思路 圖解 參考文章 開源地址 BeanDefinition 類 BeanFactory 類 測試類 什么是 Springbean 容器 Spring 包含并管理應用對象的配置和生命周期&#xff0c;在這個意義上它是一種用于承載對象的容器&#xff0c;你可以配置你的每個 Bea…

AI Agent開發大全第十四課-零售智能導購智能體的RAG開發理論部分

開篇 經過前面的一些課程,我們手上已經積累了各種LLM的API調用、向量庫的建立和使用、embedding算法的意義和基本使用。 這已經為我們具備了開發一個基本的問答類RAG的開發必需要素了。下面我們會來講一個基本問答類場景的RAG,零售中的“智能導購”場景。 智能導購 大家先…

向字符串添加空格

給你一個下標從 0 開始的字符串 s &#xff0c;以及一個下標從 0 開始的整數數組 spaces 。 數組 spaces 描述原字符串中需要添加空格的下標。每個空格都應該插入到給定索引處的字符值 之前 。 例如&#xff0c;s "EnjoyYourCoffee" 且 spaces [5, 9] &#xff0…

百人會上的蔚小理與「來的剛剛好」的雷軍

這就是2025百人會上的蔚小理&#xff0c;努力的李斌、宣揚飛行汽車的何小鵬與大講開源的李想。那么小米汽車的模式是什么呢&#xff1f;站在蔚小理的肩上。 這就是2025百人會上的蔚小理&#xff0c;努力的李斌、宣揚飛行汽車的何小鵬與大講開源的李想。那么小米汽車的模式是什么…

解鎖Nginx路由器匹配規則

引言 Nginx 無疑是一款備受矚目的明星產品。它以其高性能、高可靠性以及出色的并發處理能力&#xff0c;在眾多 Web 服務器和反向代理服務器中脫穎而出 &#xff0c;廣泛應用于各類網站和應用程序中。據統計&#xff0c;超過 30% 的網站都在使用 Nginx 作為其 Web 服務器&…