欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java線程池ThreadPoolExecutor實現(xiàn)原理詳解

 更新時間:2023年12月16日 10:57:29   作者:那個天真的人  
這篇文章主要介紹了java線程池ThreadPoolExecutor實現(xiàn)原理詳解,ThreadPoolExecutor是線程池實現(xiàn)類,會動態(tài)創(chuàng)建多個線程,并發(fā)執(zhí)行提交的多個任務(wù),需要的朋友可以參考下

前言

做java開發(fā)的,一般都避免不了要面對java線程池技術(shù),像tomcat之類的容器天然就支持多線程。

即使是做偏后端技術(shù),如處理一些消息,執(zhí)行一些計算任務(wù),也經(jīng)常需要用到線程池技術(shù)。

鑒于線程池技術(shù)的重要性,接下來會分多篇介紹java中提供的ThreadPoolExecutor線程池實現(xiàn)的底層機制。

只有對機制了然于胸,才能更好駕馭這把利器。

線程池技術(shù)演示流程

  • 關(guān)鍵概念: 如果說怎么最容易了解線程池的實現(xiàn)原理,那就是一步一步動態(tài)的演示。為了便于理解,這里先介紹幾個線程池用到的概念。
  • ThreadPoolExecutor: 這是線程池實現(xiàn)類,會動態(tài)創(chuàng)建多個線程,并發(fā)執(zhí)行提交的多個任務(wù);
  • Worker: 是個Runnable實現(xiàn)類來的,內(nèi)部會創(chuàng)建一個線程,一直循環(huán)不斷執(zhí)行任務(wù),所以可以認為一個Worker就是一個工作線程;
  • corePoolSize: 當池中總線程數(shù)<corePoolSize時,提交一個任務(wù)創(chuàng)建一個新線程,而不管已經(jīng)存在的線程是不是閑著,通常情況下,一旦線程數(shù)達 到了corePoolSize,那么池中總線程數(shù)是不會跌破到corePoolSize以下的。(除非 allowCoreThreadTimeOut=true并且keepAliveTime>0);
  • maximumPoolSize: 當池中線程數(shù)達到了corePoolSize,這時候新提交的任務(wù)就會放入等待隊列中,一般情況下,這些任務(wù)會被前面創(chuàng)建的 corePoolSize個線程執(zhí)行。當任務(wù)提交速度過快,隊列滿了,這時候,如果當前總線程數(shù)<maximumPoolSize,那么線程池會創(chuàng)建一個新的線程來執(zhí)行新提交的任務(wù),否則根據(jù)策略放棄任務(wù);
  • keepAliveTime:存活時間,分兩種情況: (1)allowCoreThreadTimeOut=true,所有線程,一旦創(chuàng)建后,在keepAliveTime時間內(nèi),如果沒有任務(wù)可以執(zhí)行,則該線程會退出并銷毀,這樣的好處是系統(tǒng)不忙時可以回收線程資源;(2)allowCoreThreadTimeOut=false,如果總線程數(shù)<=corePoolSize,那么這些線程是不會退出的,他們會一直不斷的等待任務(wù)并執(zhí)行,哪怕當前沒有任務(wù),但如果線程數(shù)>corePoolSize,而且一旦一個線程閑的時間超過 keepAliveTime則會退出,但一旦降低到corePoolSize,則不會再退出了。
  • allowCoreThreadTimeOut: 用于決定是否在系統(tǒng)閑時可以逐步回收所有的線程,如果為allowCoreThreadTimeOut=true,必須結(jié)合keepAliveTime一起使用,用于決定當線程數(shù)<corePoolSize時,是否要回收這些線程。
  • workQueue:這是一個阻塞隊列,當線程數(shù)>=corePoolSize,這時候提交的任務(wù)將會放入阻塞隊列中,如果阻塞隊列是無界的,那么總的線程數(shù)是不可能>corePoolSize的,即maximumPoolSize屬性就是無用的;如果阻塞隊列是有界的,而且未滿,則任務(wù)入隊,否則根據(jù)maximumPoolSize的值判斷是要新建線程執(zhí)行新任務(wù)或者是根據(jù)策略丟棄任務(wù)。

有了以上的概念,接下來將根據(jù) allowCoreThreadTimeOut的值分兩種場景進行演示說明。

演示一: allowCoreThreadTimeOut=true

1、 初值設(shè)定: corePoolSize=2; maximumPoolSize=3;keepAliveTime=10s; workQueue容量為2; 初始狀態(tài)圖如下所示:

這里寫圖片描述

2、submit一個任務(wù)A,由于總線程數(shù)0<corePoolSize; 此時會創(chuàng)建一個線程執(zhí)行任務(wù)A,狀態(tài)圖如下:

這里寫圖片描述

3、submit一個任務(wù)B,由于總線程數(shù)1<corePoolSize,此時會創(chuàng)建一個線程執(zhí)行任務(wù)B,狀態(tài)圖如下:

這里寫圖片描述

4、submit一個任務(wù)C,由于總線程數(shù) 2=corePoolSize,workQueue不滿,這時候任務(wù)C入隊列,狀態(tài)圖如下:

這里寫圖片描述

5、submit一個任務(wù)D,很明顯,任務(wù)D入隊列,狀態(tài)圖如下:

這里寫圖片描述

6、submit一個任務(wù)E,這時候,線程數(shù)2=corePoolSize,workQueue也已經(jīng)滿了,判斷發(fā)現(xiàn)線程數(shù)2<maximumPoolSize,所以繼續(xù)創(chuàng)建線程執(zhí)行任務(wù)E,狀態(tài)圖如下:

這里寫圖片描述

7、submit一個任務(wù)F,這時候,2=corePoolSize,workQueue已滿,判斷發(fā)現(xiàn)線程數(shù)3=maximumPoolSize,這種情況下,線程池會根據(jù)策略來決定是否要放棄當前任務(wù),或者是把workQueue中一個任務(wù)刪除,然后入隊新的任務(wù),也可以自定義策略,比如,持久化到DB之類的,或者是發(fā)出警報。我們假設(shè)是直接丟棄策略,這時候狀態(tài)圖不變。

8、這會沒有新任務(wù)到來了,各個任務(wù)陸續(xù)執(zhí)行完了,包括隊列中的C和D也執(zhí)行完了,這時候,由于當前場景為allowCoreThreadTimeOut=true,如果在等待keepAliveTime時間后線程仍舊無法獲取新的任務(wù),線程將會自行退出,這將導致最終所有線程都退出了,也就是又再次回到了原始狀態(tài),如下圖所示:

這里寫圖片描述

說得更簡單一些就是:在 allowCoreThreadTimeOut=true時,如果一個線程等了keepAliveTime還無法獲取新任務(wù),則退出。

演示二:allowCoreThreadTimeOut=false

1~7 的步驟與狀態(tài)跟“演示一”是一樣的,所以這里不再贅述,這時候狀態(tài)圖如下:

這里寫圖片描述

8、這會沒有新任務(wù)到來了,各個任務(wù)陸續(xù)執(zhí)行完了,包括隊列中的C和D也執(zhí)行完了,這時候,由于當前場景為allowCoreThreadTimeOut=false,并且線程數(shù)3>corePoolSize,這時候每個線程都感知到線程數(shù)過多,所以它們都會嘗試把自己停止掉,實現(xiàn)中最終只會停止一個線程,剩余線程數(shù)2=corePoolSize,接下來,哪怕一直沒有新任務(wù)來,這corePoolSize個線程也不會退出,一直存活著等待接收任務(wù)。這時候,狀態(tài)圖如下:

這里寫圖片描述

線程池的狀態(tài)

前一部分演示了線程池的基本實現(xiàn)原理,這一小節(jié)介紹一下線程池的狀態(tài),線程池概括上講有5種狀態(tài),如下圖所示:

這里寫圖片描述

  • RUNNING狀態(tài): 創(chuàng)建線程池的時候,線程池的初始狀態(tài)為 RUNNING,接著就可以提交任務(wù)執(zhí)行了。
  • SHUTDOWN狀態(tài): 當在RUNNING狀態(tài)調(diào)用shutdown()時,線程池狀態(tài)會被改為SHUTDOWN,這時候,submit任務(wù)的時候,會被拒絕,可以使用多種拒絕策略, 比如最簡單就是直接丟棄任務(wù)。至于正在執(zhí)行中的線程,會繼續(xù)執(zhí)行,同時會把阻塞隊列中的任務(wù)也一并執(zhí)行完畢,等到全部任務(wù)執(zhí)行完畢,線程池會進入 TIDYING狀態(tài),等執(zhí)行鉤子方法terminated()之后,就會進入最終狀態(tài)TERMINATED,這時候,整個線程池完全終止。
  • STOP狀態(tài): 當在RUNNING狀態(tài)調(diào)用shutdownNow()時,線程池狀態(tài)會被改為STOP,這時候,submit任務(wù)會被拒絕,那么如果有任務(wù)執(zhí)行到一半,該怎么處理?其實,執(zhí)行shutdownNow()時,會中斷各個工作線程,所以任務(wù)會如何執(zhí)行要看任務(wù)做的是什么事情,有沒有處理中斷異常。而阻塞隊列如何有任務(wù),這些任務(wù)將不會再執(zhí)行,shutdownNow()執(zhí)行后,將會返回阻塞隊列中的未執(zhí)行的任務(wù)列表。
  • TIDYING狀態(tài): TIDYING只是一個過渡狀態(tài),當所有工作線程都停止后,線程池的狀態(tài)會進入TIDYING,然后執(zhí)行一個鉤子方法terminated(),最后線程池會進入TERMINATED狀態(tài)。
  • TERMINATED狀態(tài): 線程池終止狀態(tài),這個沒什么可說的了,大家都明白。

總結(jié)

理解線程池最主要是要理解線程池幾個主要的配置參數(shù),如果不看實現(xiàn)細節(jié),原理還是比較簡單的。在了解原理的基礎(chǔ)上再去看代碼,就會事半功倍。

到此這篇關(guān)于java線程池ThreadPoolExecutor實現(xiàn)原理詳解的文章就介紹到這了,更多相關(guān)ThreadPoolExecutor實現(xiàn)原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決Sentinel鏈路模式規(guī)則無效問題

    解決Sentinel鏈路模式規(guī)則無效問題

    本文介紹了如何在Spring Cloud Alibaba項目中使用Sentinel鏈路流控規(guī)則,并解決規(guī)則不生效的問題,通過關(guān)閉Sentinel過濾器,可以避免重復統(tǒng)計請求
    2025-01-01
  • java實現(xiàn)即賦值也判斷的寫法示例

    java實現(xiàn)即賦值也判斷的寫法示例

    這篇文章主要為大家介紹了java實現(xiàn)即賦值也判斷的寫法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • 詳解Java8新特性之interface中的static方法和default方法

    詳解Java8新特性之interface中的static方法和default方法

    這篇文章主要介紹了Java8新特性之interface中的static方法和default方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-08-08
  • java貪心算法初學感悟圖解及示例分享

    java貪心算法初學感悟圖解及示例分享

    這篇文章主要為大家介紹了本人在初學java貪心算法的感悟,并通過圖解及示例代碼的方式分享給大家,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-11-11
  • Java Map的幾種循環(huán)方式總結(jié)

    Java Map的幾種循環(huán)方式總結(jié)

    這篇文章主要是對Java中Map的幾種循環(huán)方式進行了詳細的總結(jié)介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2013-12-12
  • Java如何接收前端easyui?datagrid傳遞的數(shù)組參數(shù)

    Java如何接收前端easyui?datagrid傳遞的數(shù)組參數(shù)

    這篇文章分享一下怎么在easyui的datagrid刷新表格時,在后端java代碼中接收datagrid傳遞的數(shù)組參數(shù),本文通過實例代碼給大家介紹的非常詳細,需要的朋友參考下吧
    2023-11-11
  • Spring Boot Admin實踐詳解

    Spring Boot Admin實踐詳解

    在本篇文章里小編給大家整理了關(guān)于Spring Boot Admin實踐的相關(guān)知識點,有需要的朋友們可以學習下。
    2019-12-12
  • Java基本數(shù)據(jù)類型與對應(yīng)的包裝類(動力節(jié)點java學院整理)

    Java基本數(shù)據(jù)類型與對應(yīng)的包裝類(動力節(jié)點java學院整理)

    Java是面向?qū)ο蟮木幊陶Z言,包裝類的出現(xiàn)更好的體現(xiàn)這一思想,Java語言提供了八種基本類型。六種數(shù)字類型(四個整數(shù)型,兩個浮點型),一種字符類型,還有一種布爾型。 下面通過本文給大家詳細介紹,感興趣的朋友一起學習吧
    2017-04-04
  • SpringBoot框架DataSource多數(shù)據(jù)源配置方式

    SpringBoot框架DataSource多數(shù)據(jù)源配置方式

    這篇文章主要介紹了SpringBoot框架DataSource多數(shù)據(jù)源配置方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java中的ByteArrayInputStream詳解

    Java中的ByteArrayInputStream詳解

    Java中,ByteArrayInputStream類是實現(xiàn)內(nèi)存級別的字節(jié)流讀取的工具,可以從字節(jié)數(shù)組中讀取數(shù)據(jù),這個類位于java.io包中,繼承自InputStream,ByteArrayInputStream的主要特點有:在內(nèi)存中操作,不涉及磁盤IO,可以重用流讀取數(shù)據(jù)
    2024-09-09

最新評論