最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談Java線程池的7大核心參數(shù)

 更新時間:2021年05月13日 09:38:57   作者:你走吧起風了__  
本篇文章基于正在看這篇文章的你已經(jīng)具備了基本的Java并發(fā)的相關知識.如果對于Java并發(fā)編程一無所知的話,請先看看Java并發(fā)編程的一些前導基礎知識,文中有非常詳細的圖文示例及代碼,,需要的朋友可以參考下

前言

java中經(jīng)常需要用到多線程來處理一些業(yè)務,我不建議單純使用繼承Thread或者實現(xiàn)Runnable接口的方式來創(chuàng)建線程,那樣勢必有創(chuàng)建及銷毀線程耗費資源、線程上下文切換問題。

同時創(chuàng)建過多的線程也可能引發(fā)資源耗盡的風險,這個時候引入線程池比較合理,方便線程任務的管理。

java中涉及到線程池的相關類均在jdk1.5開始的java.util.concurrent包中,涉及到的幾個核心類及接口包括:

Executor、Executors、ExecutorService、ThreadPoolExecutor、FutureTask、Callable、Runnable等。

一、線程池的創(chuàng)建及重要參數(shù)

線程池可以自動創(chuàng)建也可以手動創(chuàng)建,自動創(chuàng)建體現(xiàn)在Executors工具類中,常見的可以創(chuàng)建newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor、newScheduledThreadPool;

手動創(chuàng)建體現(xiàn)在可以靈活設置線程池的各個參數(shù),體現(xiàn)在代碼中即ThreadPoolExecutor類構造器上各個實參的不同:

 public static ExecutorService newFixedThreadPool(int var0) {
        return new ThreadPoolExecutor(var0, var0, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
  }
	
  public static ExecutorService newSingleThreadExecutor() {
        return new Executors.FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()));
  }
 
  public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue());
  }
 
  public static ScheduledExecutorService newScheduledThreadPool(int var0) {
        return new ScheduledThreadPoolExecutor(var0);
  }

(重點)

public ThreadPoolExecutor(int corePoolSize,
                           int maximumPoolSize,
                           long keepAliveTime,
                           TimeUnit unit,
                           BlockingQueue<Runnable> workQueue,
                           ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {……}

二、ThreadPoolExecutor中重要的幾個參數(shù)詳解

  •  corePoolSize:核心線程數(shù),也是線程池中常駐的線程數(shù),線程池初始化時默認是沒有線程的,當任務來臨時才開始創(chuàng)建線程去執(zhí)行任務
  • maximumPoolSize:最大線程數(shù),在核心線程數(shù)的基礎上可能會額外增加一些非核心線程,需要注意的是只有當workQueue隊列填滿時才會創(chuàng)建多于corePoolSize的線程(線程池總線程數(shù)不超過maxPoolSize)
  • keepAliveTime:非核心線程的空閑時間超過keepAliveTime就會被自動終止回收掉,注意當corePoolSize=maxPoolSize時,keepAliveTime參數(shù)也就不起作用了(因為不存在非核心線程);
  • unit:keepAliveTime的時間單位
  • workQueue:用于保存任務的隊列,可以為無界、有界、同步移交三種隊列類型之一,當池子里的工作線程數(shù)大于corePoolSize時,這時新進來的任務會被放到隊列中
  • threadFactory:創(chuàng)建線程的工廠類,默認使用Executors.defaultThreadFactory(),也可以使用guava庫的ThreadFactoryBuilder來創(chuàng)建
  • handler:線程池無法繼續(xù)接收任務(隊列已滿且線程數(shù)達到maximunPoolSize)時的飽和策略,取值有AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy、DiscardPolicy

 線程池中的線程創(chuàng)建流程圖:

(基于<Java并發(fā)編程的藝術>一書)

舉個例子:

現(xiàn)有一個線程池,corePoolSize=10,maxPoolSize=20,隊列長度為100,那么當任務過來會先創(chuàng)建10個核心線程數(shù),接下來進來的任務會進入到隊列中直到隊列滿了,會創(chuàng)建額外的線程來執(zhí)行任務(最多20個線程),這個時候如果再來任務就會執(zhí)行拒絕策略。

三、workQueue隊列(阻塞隊列)

SynchronousQueue(同步移交隊列):隊列不作為任務的緩沖方式,可以簡單理解為隊列長度為零LinkedBlockingQueue(無界隊列):隊列長度不受限制,當請求越來越多時(任務處理速度跟不上任務處理速度造成請求堆積)可能導致內(nèi)存占用過多或OOMArrayBlockintQueue(有界隊列):隊列長度受限,當隊列滿了就需要創(chuàng)建多余的線程來執(zhí)行任務

四、常見的幾種自動創(chuàng)建線程池方式

自動創(chuàng)建線程池的幾種方式都封裝在Executors工具類中:


newFixedThreadPool:使用的構造方式為new ThreadPoolExecutor(var0, var0, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()),設置了corePoolSize=maxPoolSize,keepAliveTime=0(此時該參數(shù)沒作用),無界隊列,任務可以無限放入,當請求過多時(任務處理速度跟不上任務提交速度造成請求堆積)可能導致占用過多內(nèi)存或直接導致OOM異常
newSingleThreadExector:使用的構造方式為new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), var0),基本同newFixedThreadPool,但是將線程數(shù)設置為了1,單線程,弊端和newFixedThreadPool一致


newCachedThreadPool: 使用的構造方式為new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue()),corePoolSize=0,maxPoolSize為很大的數(shù),同步移交隊列,也就是說不維護常駐線程(核心線程),每次來請求直接創(chuàng)建新線程來處理任務,也不使用隊列緩沖,會自動回收多余線程,由于將maxPoolSize設置成Integer.MAX_VALUE,當請求很多時就可能創(chuàng)建過多的線程,導致資源耗盡OOM


newScheduledThreadPool:使用的構造方式為new ThreadPoolExecutor(var1, 2147483647, 0L, TimeUnit.NANOSECONDS, new ScheduledThreadPoolExecutor.DelayedWorkQueue()),支持定時周期性執(zhí)行,注意一下使用的是延遲隊列,弊端同newCachedThreadPool一致

所以根據(jù)上面分析我們可以看到,F(xiàn)ixedThreadPool和SigleThreadExecutor中之所以用LinkedBlockingQueue無界隊列,是因為設置了corePoolSize=maxPoolSize,線程數(shù)無法動態(tài)擴展,于是就設置了無界阻塞隊列來應對不可知的任務量;而CachedThreadPool則使用的是SynchronousQueue同步移交隊列,為什么使用這個隊列呢?

因為CachedThreadPool設置了corePoolSize=0,maxPoolSize=Integer.MAX_VALUE,來一個任務就創(chuàng)建一個線程來執(zhí)行任務,用不到隊列來存儲任務;SchduledThreadPool用的是延遲隊列DelayedWorkQueue。在實際項目開發(fā)中也是推薦使用手動創(chuàng)建線程池的方式,而不用默認方式。

關于這點在《阿里巴巴開發(fā)規(guī)范》中是這樣描述的:

handler拒絕策略

  • AbortPolicy:中斷拋出異常
  • DiscardPolicy:默默丟棄任務,不進行任何通知
  • DiscardOldestPolicy:丟棄掉在隊列中存在時間最久的任務
  • CallerRunsPolicy:讓提交任務的線程去執(zhí)行任務(對比前三種比較友好一丟丟

關閉線程池

  • shutdownNow():立即關閉線程池(暴力),正在執(zhí)行中的及隊列中的任務會被中斷,同時該方法會返回被中斷的隊列中的任務列表
  • shutdown():平滑關閉線程池,正在執(zhí)行中的及隊列中的任務能執(zhí)行完成,后續(xù)進來的任務會被執(zhí)行拒絕策略i
  • sTerminated():當正在執(zhí)行的任務及對列中的任務全部都執(zhí)行(清空)完就會返回true。

五、線程池實現(xiàn)線程復用的原理

   1.線程池里執(zhí)行的是任務,核心邏輯在ThreadPoolExecutor類的execute方法中,同時ThreadPoolExecutor中維護了HashSet<Worker> workers;
    2.addWorker()方法來創(chuàng)建線程執(zhí)行任務,如果是核心線程的任務,會賦值給Worker的firstTask屬性;
    3.Worker實現(xiàn)了Runnable,本質(zhì)上也是任務,核心在run()方法里;
    4.run()方法的執(zhí)行核心runWorker(),自旋拿任務while (task != null || (task = getTask()) != null)),task是核心線程Worker的firstTask或者getTask();
    5.getTask()的核心邏輯:
            1.若當前工作線程數(shù)量大于核心線程數(shù)->說明此線程是非核心工作線程,通過poll()拿任務,未拿到任務即getTask()返回null,然后會在processWorkerExit(w, completedAbruptly)方法釋放掉這個非核心工作線程的引用;
            2.若當前工作線程數(shù)量小于核心線程數(shù)->說明此時線程是核心工作線程,通過take()拿任務
            3.take()方式取任務,如果隊列中沒有任務了會調(diào)用await()阻塞當前線程,直到新任務到來,所以核心工作線程不會被回收; 當執(zhí)行execute方法里的workQueue.offer(command)時會調(diào)用Condition.singal()方法喚醒一個之前阻塞的線程,這樣核心線程即可復用
 

六、手動創(chuàng)建線程池(推薦)

那么上面說了使用Executors工具類創(chuàng)建的線程池有隱患,那如何使用才能避免這個隱患呢?對癥下藥,建立自己的線程工廠類,靈活設置關鍵參數(shù):

//這里默認拒絕策略為AbortPolicy
private static ExecutorService executor = new ThreadPoolExecutor(10,10,60L, TimeUnit.SECONDS,new ArrayBlockingQueue(10));

使用guava包中的ThreadFactoryBuilder工廠類來構造線程池:

private static ThreadFactory threadFactory = new ThreadFactoryBuilder().build();
 
private static ExecutorService executorService = new ThreadPoolExecutor(10, 10, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10), threadFactory, new ThreadPoolExecutor.AbortPolicy());

通過guava的ThreadFactory工廠類還可以指定線程組名稱,這對于后期定位錯誤時也是很有幫助的

ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("thread-pool-d%").build();

七、Springboot中使用線程池

springboot可以說是非常流行了,下面說說如何在springboot中優(yōu)雅的使用線程池

/**
 * @ClassName ThreadPoolConfig
 * @Description 配置類中構建線程池實例,方便調(diào)用
 * @Author ww
 * @Date 2021/5/11
 * Version  1.0
 */
@Configuration
public class ThreadPoolConfig {
    @Bean(value = "threadPoolInstance")
    public ExecutorService createThreadPoolInstance() {
        //通過guava類庫的ThreadFactoryBuilder來實現(xiàn)線程工廠類并設置線程名稱
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("thread-pool-%d").build();
        ExecutorService threadPool = new ThreadPoolExecutor(10, 16, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100), threadFactory, new ThreadPoolExecutor.AbortPolicy());
        return threadPool;
    }
}
/**
 * @ClassName ThreadPoolConfig
 * @Description 配置類中構建線程池實例,方便調(diào)用
 * @Author ww
 * @Date 2021/5/11
 * Version  1.0
 */
@Configuration
public class ThreadPoolConfig {
    @Bean(value = "threadPoolInstance")
    public ExecutorService createThreadPoolInstance() {
        //通過guava類庫的ThreadFactoryBuilder來實現(xiàn)線程工廠類并設置線程名稱
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("thread-pool-%d").build();
        ExecutorService threadPool = new ThreadPoolExecutor(10, 16, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100), threadFactory, new ThreadPoolExecutor.AbortPolicy());
        return threadPool;
    }
}

其它相關

在ThreadPoolExecutor類中有兩個比較重要的方法引起了我的注意:beforeExecute和afterExecute

 protected void beforeExecute(Thread var1, Runnable var2) {
 }
 
 protected void afterExecute(Runnable var1, Throwable var2) {
 }

這兩個方法是protected修飾的,很顯然是留給開發(fā)人員去重寫方法體實現(xiàn)自己的業(yè)務邏輯,非常適合做鉤子函數(shù),在任務run方法的前后增加業(yè)務邏輯,比如添加日志、統(tǒng)計等。

這個和我們springmvc中攔截器的preHandle和afterCompletion方法很類似,都是對方法進行環(huán)繞,類似于spring的AOP。

到此這篇關于淺談Java線程池的7大核心參數(shù)的文章就介紹到這了,更多相關Java線程池核心參數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java RabbitMQ的三種Exchange模式

    Java RabbitMQ的三種Exchange模式

    這篇文章主要介紹了Java RabbitMQ的三種Exchange模式,分別為Direct模式、Fanout模式、Topic模式,Rabbit的Direct Exchange模式是指消息發(fā)送導RouteKey中指定的Queue,Direct模式可以使用Rabbit自帶的Exchange
    2022-08-08
  • 如何解決maven搭建一直處于running:..狀態(tài)問題

    如何解決maven搭建一直處于running:..狀態(tài)問題

    在使用Maven搭建項目時,有時會遇到一直處于加載狀態(tài)的情況,通過修改設置可以解決這個問題,具體步驟為:1. 打開File->Settings->Build, Execution, Deployment->Maven->running,然后在VMOptions中填寫"-DarchetypeCatalog=internal"
    2024-09-09
  • MyBatis查詢返回Map示例代碼

    MyBatis查詢返回Map示例代碼

    這篇文章主要給大家介紹了關于MyBatis查詢返回Map的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-10-10
  • Hibernate緩存機制實例代碼解析

    Hibernate緩存機制實例代碼解析

    這篇文章主要介紹了Hibernate緩存機制實例代碼解析,介紹了查詢緩存,一級二級緩存等內(nèi)容,分享了相關代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • IDEA無法打開Marketplace的三種解決方案(推薦)

    IDEA無法打開Marketplace的三種解決方案(推薦)

    這篇文章主要介紹了IDEA無法打開Marketplace的三種解決方案(推薦),本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • JVM鉤子函數(shù)的使用場景詳解

    JVM鉤子函數(shù)的使用場景詳解

    當jvm進程退出的時候,或者受到了系統(tǒng)的中斷信號,hook線程就會啟動,一個線程可以注入多個鉤,下面這篇文章主要給大家介紹了關于JVM鉤子函數(shù)使用的相關資料,需要的朋友可以參考下
    2021-08-08
  • Java實戰(zhàn)角色權限后臺腳手架系統(tǒng)的實現(xiàn)流程

    Java實戰(zhàn)角色權限后臺腳手架系統(tǒng)的實現(xiàn)流程

    只學書上的理論是遠遠不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+Springboot+Maven+myBaits-Plus+Vue+Element-UI+Mysql實現(xiàn)一個角色權限后臺腳手架系統(tǒng),大家可以在過程中查缺補漏,提升水平
    2022-01-01
  • Java 互相關聯(lián)的實體無限遞歸問題的解決

    Java 互相關聯(lián)的實體無限遞歸問題的解決

    這篇文章主要介紹了Java 互相關聯(lián)的實體無限遞歸問題的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java為什么基本數(shù)據(jù)類型不需要進行創(chuàng)建對象?

    Java為什么基本數(shù)據(jù)類型不需要進行創(chuàng)建對象?

    今天小編就為大家分享一篇關于Java為什么基本數(shù)據(jù)類型不需要進行創(chuàng)建對象?,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • Spring boot整合mybatis實現(xiàn)過程圖解

    Spring boot整合mybatis實現(xiàn)過程圖解

    這篇文章主要介紹了Spring boot整合mybatis實現(xiàn)過程圖解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08

最新評論

双辽市| 京山县| 比如县| 汉沽区| 蒲江县| 察哈| 乌苏市| 渭源县| 桐庐县| 澄城县| 遂平县| 两当县| 台湾省| 松阳县| 汕尾市| 阳朔县| 拉萨市| 巴楚县| 来安县| 澳门| 松原市| 买车| 平利县| 吐鲁番市| 郁南县| 永昌县| 九江县| 静宁县| 海伦市| 临洮县| 万盛区| 鹤岗市| 抚宁县| 拉萨市| 仙游县| 中卫市| 台湾省| 淅川县| 靖西县| 龙江县| 华池县|