日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一个DEMO让你彻底理解线程池

發布時間:2023/12/13 编程问答 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一个DEMO让你彻底理解线程池 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 一、簡介
  • 二、線程池任務場景
    • 場景一:提交5個任務,執行總耗時500ms
    • 場景二:提交10個任務,執行總耗時500ms
    • 場景三:提交11個任務,執行總耗時1000ms
    • 場景四:提交20個任務,執行總耗時1000ms
    • 場景五:提交30個任務,執行總耗時1500ms
    • 場景六:提交40個任務,執行總耗時2000ms
    • 場景七:提交41個任務,執行總耗時2000ms
    • 場景八:提交45個任務,執行總耗時1500ms
    • 場景九:提交50個任務,執行總耗時1500ms
    • 場景十:提交51個任務,執行總耗時1500ms
  • 三、總結


線程池原理詳見:Java基礎——深入理解Java線程池

一、簡介

網上有很多關于 線程池原理 的講解,理論說的多了你也不一定記得住,也不一定理解的了,下面我通過一個DEMO,加上多個任務場景,讓你能夠直觀的理解線程池的工作流程。


二、線程池任務場景

線程池有幾個關鍵參數:核心線程數、最大線程數、回收時間、隊列等。

我們DEMO使用自定義線程池方式來講解線程池的工作流程,代碼如下:

package com.example.springbootdemo.util;import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger;public class ThreadPoolTest {// 任務數private static int taskCount = 50;// 實際完成任務數private static AtomicInteger taskCountExecuted;public static void main(String[] args) {init();}private static void init(){taskCountExecuted = new AtomicInteger(0);ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, // 核心線程數20, // 最大線程數5, // 非核心線程回收超時時間TimeUnit.SECONDS, // 超時時間單位new ArrayBlockingQueue<>(30) // 任務隊列);System.out.println("任務總數 = [" + taskCount + "]個");long start = System.currentTimeMillis();for(int i=0; i<taskCount; i++){Runnable runnable = new Runnable() {@Overridepublic void run() {try{Thread.sleep(500);System.out.println("已執行第 [" + taskCountExecuted.addAndGet(1) + "] 個任務");}catch (Exception ex){ex.printStackTrace();}}};try{// 默認拒絕策略會報錯threadPoolExecutor.execute(runnable);}catch (Exception ex){ex.printStackTrace();taskCount = threadPoolExecutor.getActiveCount() + threadPoolExecutor.getQueue().size();}}long end = 0;while (threadPoolExecutor.getCompletedTaskCount() < taskCount){end = System.currentTimeMillis();}System.out.println("[" + taskCountExecuted + "]個任務執行總耗時 = [" + (end - start) + "]ms");threadPoolExecutor.shutdown();} }

說明:我們DEMO中新建了個線程池,核心線程數10,最大線程數20,任務隊列容量30。

執行每個任務場景只需修改 taskCount 值即可。


場景一:提交5個任務,執行總耗時500ms

taskCount = 5;

執行結果:

任務總數 = [5]個 已執行第 [2] 個任務 已執行第 [3] 個任務 已執行第 [4] 個任務 已執行第 [1] 個任務 已執行第 [5] 個任務 [5]個任務執行總耗時 = [506]ms

分析:核心線程數為10,也就是說有10個線程數長期處于活動狀態,即來任務立馬就能執行,任務數5 < 核心線程數10,所以,5個任務立馬執行完成,且是多線程并行執行,所以任務執行總耗時 = 500ms

注:我們日志輸出的是 505ms ,因為代碼執行也是要花時間的。


場景二:提交10個任務,執行總耗時500ms

taskCount = 10;

執行結果:

任務總數 = [10]個 已執行第 [2] 個任務 已執行第 [8] 個任務 已執行第 [5] 個任務 ... 已執行第 [3] 個任務 已執行第 [9] 個任務 已執行第 [10] 個任務 [10]個任務執行總耗時 = [507]ms

分析:任務數10 <= 核心線程數10,10個任務立馬執行完成,所以任務執行總耗時 = 500ms。


場景三:提交11個任務,執行總耗時1000ms

taskCount = 11;

執行結果:

任務總數 = [11]個 已執行第 [1] 個任務 已執行第 [3] 個任務 已執行第 [4] 個任務 ... 已執行第 [8] 個任務 已執行第 [7] 個任務 已執行第 [11] 個任務 [11]個任務執行總耗時 = [1009]ms

分析:任務執行總耗時 = 1000ms,別驚訝,這里是很多人沒有搞懂線程池運行機制的關鍵點,雖然任務只多個一個,但是地11個任務不是立馬執行的,核心線程數為10,第11個任務會進入到任務隊列,等核心線程有空出來后會從任務隊列中取出任務再來執行,因此任務總耗時 = 1000ms。


場景四:提交20個任務,執行總耗時1000ms

taskCount = 20;

執行結果:

任務總數 = [20]個 已執行第 [5] 個任務 已執行第 [4] 個任務 已執行第 [2] 個任務 ... 已執行第 [16] 個任務 已執行第 [19] 個任務 已執行第 [20] 個任務 [20]個任務執行總耗時 = [1010]ms

分析:任務執行總耗時 = 1000ms,此處與前一個場景一樣,第11到第20共10個任務會進入到任務隊列,等核心線程有空出來后會從任務隊列中取出任務再來執行,因為有10個核心線程,前10個任務執行完成后,任務隊列中的10個任務正好由空出的10個核心線程來執行,因此任務總耗時 = 1000ms。


場景五:提交30個任務,執行總耗時1500ms

taskCount = 30;

執行結果:

任務總數 = [30]個 已執行第 [2] 個任務 已執行第 [6] 個任務 已執行第 [3] 個任務 ... 已執行第 [23] 個任務 已執行第 [25] 個任務 已執行第 [30] 個任務 [30]個任務執行總耗時 = [1514]ms

分析:任務執行總耗時 = 1500ms,此處與前一個場景一樣,第11到第30共20個任務會進入到任務隊列,等核心線程有空出來后會從任務隊列中取出任務再來執行,因為有10個核心線程,前10個任務執行完成后,從任務隊列中取出10個任務由空出的10個核心線程來執行,執行完后在取出10個任務來執行,因此任務總耗時 = 1500ms。


場景六:提交40個任務,執行總耗時2000ms

taskCount = 40;

執行結果:

任務總數 = [40]個 已執行第 [1] 個任務 已執行第 [2] 個任務 已執行第 [4] 個任務 ... 已執行第 [32] 個任務 已執行第 [34] 個任務 已執行第 [40] 個任務 [40]個任務執行總耗時 = [2016]ms

分析:任務執行總耗時 = 2000ms,此處與前一個場景一樣,這里不再過多解釋。


場景七:提交41個任務,執行總耗時2000ms

taskCount = 41;

執行結果:

任務總數 = [41]個 已執行第 [1] 個任務 已執行第 [2] 個任務 已執行第 [3] 個任務 ... 已執行第 [40] 個任務 已執行第 [37] 個任務 已執行第 [41] 個任務 [41]個任務執行總耗時 = [2016]ms

分析:任務執行總耗時 = 2000ms,這里重點來了,我們知道第11到第40共30個任務進入到了任務隊列中(任務隊列大小為30),第41個任務就創建了一個非核心線程(最大線程數20 - 核心線程數10 = 10個非核心線程)來執行,此時線程池中的活躍線程數為11,第一批任務執行完后,會從任務隊列中取出11個任務來執行,那就是 11 + 11 + 11 + 8 = 500ms * 4 = 2000ms。


場景八:提交45個任務,執行總耗時1500ms

taskCount = 45;

執行結果:

任務總數 = [45]個 已執行第 [3] 個任務 已執行第 [4] 個任務 ... 已執行第 [43] 個任務 已執行第 [42] 個任務 已執行第 [45] 個任務 [45]個任務執行總耗時 = [1516]ms

分析:任務執行總耗時 = 1500ms,此處與前一個場景一樣,我們知道第11到第40共30個任務進入到了任務隊列中(任務隊列大小為30),第41到第45共5個任務就創建了5個非核心線程(最大線程數20 - 核心線程數10 = 10個非核心線程)來執行,此時線程池中的活躍線程數為15,第一批任務執行完后,會從任務隊列中取出15個任務來執行,那就是 15 + 15 + 15 = 500ms * 3 = 1500ms。


場景九:提交50個任務,執行總耗時1500ms

taskCount = 50;

執行結果:

任務總數 = [50]個 已執行第 [1] 個任務 已執行第 [9] 個任務 已執行第 [12] 個任務 ... 已執行第 [45] 個任務 已執行第 [44] 個任務 已執行第 [50] 個任務 [50]個任務執行總耗時 = [1515]ms

分析:任務執行總耗時 = 1500ms,此處與前一個場景一樣,我們知道第11到第40共30個任務進入到了任務隊列中(任務隊列大小為30),第41到第50共10個任務就創建了10個非核心線程(最大線程數20 - 核心線程數10 = 10個非核心線程)來執行,此時線程池中的活躍線程數為20,第一批任務執行完后,會從任務隊列中取出20個任務來執行,那就是 20 + 20 + 10 = 500ms * 3 = 1500ms。


場景十:提交51個任務,執行總耗時1500ms

taskCount = 10;

執行結果:

任務總數 = [51]java.util.concurrent.RejectedExecutionException: Task com.example.springbootdemo.util.ThreadPoolTest$1@682a0b20 rejected from java.util.concurrent.ThreadPoolExecutor@3d075dc0[Running, pool size = 20, active threads = 20, queued tasks = 30, completed tasks = 0]at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)at com.example.springbootdemo.util.ThreadPoolTest.init(ThreadPoolTest.java:48)at com.example.springbootdemo.util.ThreadPoolTest.main(ThreadPoolTest.java:16) 已執行第 [3] 個任務 已執行第 [5] 個任務 ... 已執行第 [49] 個任務 已執行第 [48] 個任務 已執行第 [50] 個任務 [50]個任務執行總耗時 = [1514]ms

分析:任務執行總耗時 = 1500ms,此處與前一個場景一樣,由于線程池同時最大能接收50個任務(最大線程數20 + 任務隊列大小30 = 50),所以第51個任務被拒絕了(線程池使用默認拒絕策略AbortPolicy),拋出了異常,DEMO中使用了try-catch捕獲到了。


三、總結

  • 任務數 <= 核心線程數,線程池中工作線程數 = 任務數;

  • 核心線程數 < 任務數 <= (核心線程數 + 隊列容量)時,線程池中工作線程數 = 核心線程數;

  • (核心線程數 + 隊列容量) < 任務數 <= (最大線程數 + 隊列容量)時,線程池中工作線程數 = (任務數 - 隊列容量);


創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的一个DEMO让你彻底理解线程池的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久久精品人妻一区二区三区四 | 久久咪咪 | 亚洲国产精品免费在线观看 | 奇米二区 | 日本一二区视频 | 一区二区三区中文字幕在线观看 | 少妇户外露出[11p] | 一区二区精品在线观看 | av香蕉 | 日韩欧美国产一区二区三区在线观看 | 在线视频97| 男女曰逼视频 | 日本加勒比一区二区 | 老司机深夜福利影院 | 99精品视频免费在线观看 | 欧美视频久久 | 国产日韩精品在线 | 99久久亚洲精品 | 秋霞影院午夜伦 | 麻豆网站免费观看 | 午夜婷婷在线观看 | 污网站在线看 | 日本高清不卡二区 | 中文在线资源 | 午夜激情婷婷 | 亚洲成色网 | 婷婷色影院| 国产av剧情一区 | 手机在线亚洲 | 亚洲 美腿 欧美 偷拍 | 光明影院手机版在线观看免费 | 日韩视频精品在线 | 欧美日韩亚洲精品内裤 | 毛片网站在线看 | 国产精品3p视频 | 中文在线最新版天堂8 | 神马电影久久 | 日本裸体xx少妇18在线 | 蜜桃免费在线视频 | 国产一级片久久 | 包射屋 | 成人午夜视频在线播放 | 亚洲黄色精品视频 | 成人免费xxxxx在线观看 | 欧美视频一区二区在线观看 | 男女做爰猛烈吃奶啪啪喷水网站 | 国产精品88| 污导航在线观看 | 18禁一区二区三区 | 五月涩| 福利片在线观看 | 欧美激情国产一区 | 亚洲视频综合网 | 日韩一卡二卡三卡四卡 | 欧美另类视频在线 | 日韩精品一区二区三区免费视频 | 精品伦精品一区二区三区视频密桃 | 亚洲伦理自拍 | 色婷婷一区二区三区四区 | 欧美久久精品一级黑人c片 1000部多毛熟女毛茸茸 | 国产精品成人免费视频 | 天天操操夜夜操操 | 丰满人妻老熟妇伦人精品 | 隔壁邻居是巨爆乳寡妇 | 日韩精品一区二区免费视频 | 成人日韩精品 | 国产精品后入内射日本在线观看 | 一区二区精品视频在线观看 | 香蕉网久久 | 国产成人在线免费观看视频 | 精品视频久久久久 | 热久久av | 黄色一级视频片 | 久久成人在线观看 | av在线免费网址 | 天天黄色片 | 国产88av | 老牛影视av老牛影视av | 国产成人无码精品久久久久 | 草久在线视频 | 精品成人一区二区三区久久精品 | 欧美一区二区三区观看 | 粉嫩av一区二区三区天美传媒 | 热精品 | 夜夜躁狠狠躁 | 精品久久久中文字幕 | 久久香蕉精品视频 | 日本成人一区二区三区 | 国产精品国产三级国产aⅴ中文 | 最新av网址在线观看 | 天天干天天做天天操 | 四虎成人精品在永久免费 | 日韩精品电影 | 含羞草一区二区 | 国产欧美日韩综合精品一区 | 香蕉911| 国产福利视频在线 | 成人精品电影 | 性视频播放免费视频 |