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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java高并发(十八)线程池

發(fā)布時(shí)間:2024/9/16 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java高并发(十八)线程池 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ? 在之前已經(jīng)使用過線程池了。在使用中,基本上就是初始化好線程池的實(shí)例之后,把任務(wù)丟進(jìn)去,等待調(diào)度執(zhí)行就可以了。使用起來非常簡(jiǎn)單方便。

new Thread弊端

  • 每次new Thread新建對(duì)象,性能差
  • 線程缺乏統(tǒng)一管理,可能無限制的新建線程,相互競(jìng)爭(zhēng),有可能占用過多系統(tǒng)資源導(dǎo)致死機(jī)或者OOM
  • 缺少更多功能,如更多執(zhí)行、定期執(zhí)行、線程中斷

線程池的好處

  • 重用存在的線程,減少對(duì)象創(chuàng)建、消亡的開銷,性能好
  • 可以有效控制最大并發(fā)線程數(shù),提高系統(tǒng)資源利用率,同時(shí)可以避免過多資源競(jìng)爭(zhēng),避免阻塞
  • 提供定時(shí)執(zhí)行、定期執(zhí)行、單線程、并發(fā)數(shù)控制等高級(jí)功能

ThreadPoolExecutor

參數(shù):

  • corePoolSize:核心線程數(shù)量。建議和cpu的核心數(shù)差不多,當(dāng)有任務(wù)提交,檢測(cè)當(dāng)前線程池內(nèi)的線程數(shù)小于corePoolSize的話,新建線程執(zhí)行任務(wù),而不會(huì)開始復(fù)用,會(huì)新建,直到達(dá)到corePoolSize。線程池內(nèi)的線程數(shù)大于等于corePoolSize時(shí),將任務(wù)放入workQueue等待。
  • maximumPoolSize:允許線程池內(nèi)最大線程數(shù)。當(dāng)隊(duì)列滿了之后,如果線程池內(nèi)的線程數(shù)小于maximumPoolSize則新建線程,如果大于等于執(zhí)行拒絕策略。
    如果maximumPoolSize是30,corePoolSize是10,當(dāng)隊(duì)列滿了后只能再開20個(gè)線程。
  • workQueue:阻塞隊(duì)列,存儲(chǔ)等待執(zhí)行的任務(wù),很重要,會(huì)對(duì)線程池運(yùn)行過程產(chǎn)生重大影響
  • keepAliveTime:線程沒有任務(wù)執(zhí)行時(shí)最多保持多久時(shí)間終止。線程池維護(hù)線程所允許的空閑時(shí)間。當(dāng)線程池中的線程數(shù)量大于CorePoolSize時(shí),如果這時(shí)沒有新的任務(wù)提交,線程會(huì)等待,直到時(shí)間超過keepAliveTime才銷毀。
  • unit:keepAliveTime的時(shí)間單位
  • threadFactory:線程工廠,用來創(chuàng)建線程,會(huì)有一個(gè)默認(rèn)的工廠來創(chuàng)建線程。使用默認(rèn)的工廠創(chuàng)建線程時(shí),線程擁有相同的優(yōu)先級(jí),并且是非守護(hù)的線程,同時(shí)也設(shè)置了線程的名稱。
  • rejectHandle:當(dāng)拒絕處理任務(wù)時(shí)的策略。如果workQueue阻塞隊(duì)列滿了,并且沒有空閑的線程時(shí),這時(shí)還繼續(xù)提交任務(wù),我們就需要一種策略來處理這個(gè)任務(wù)。線程池總共提供了四種策略:
  • 直接拋出異常,默認(rèn)策略
  • ?用調(diào)用者所在的線程執(zhí)行任務(wù)
  • 丟棄隊(duì)列中最靠前的任務(wù),并執(zhí)行當(dāng)前任務(wù)
  • 直接丟棄這個(gè)任務(wù)

????如果運(yùn)行的線程數(shù)小于CorePoolSize時(shí),直接創(chuàng)建新線程創(chuàng)建任務(wù),即使線程池中的其他線程是空閑的。

????如果線程池中的線程數(shù)量大于等于CorePoolSize且小于maximumPoolSize時(shí),則只有當(dāng)wokQueue滿時(shí)才創(chuàng)建新的線程去處理任務(wù)。

????如果我們?cè)O(shè)置CorePoolSize與maximumPoolSize相等,那么創(chuàng)建的線程池大小是固定的,這時(shí)如果有新任務(wù)提交且workQueue還沒滿,就把請(qǐng)求放入workQueue中,等待空閑線程從workQueue中取任務(wù)進(jìn)行處理。

? ? 如果運(yùn)行的線程數(shù)量大于maximumPoolSize時(shí),這時(shí)如果workQueue滿,那么會(huì)通過一個(gè)拒絕策略參數(shù)來指定策略處理任務(wù)。

? ? 如果我們想降低系統(tǒng)資源的消耗,包括CPU的使用率、操作系統(tǒng)資源的消耗,可以設(shè)置一個(gè)較大的workQueue容量和較小的CorePoolSize容量,這樣會(huì)降低線程處理的吞吐量。如果我們提交的任務(wù)經(jīng)常發(fā)生阻塞,我們可以設(shè)置maximumPoolSize來設(shè)置線程池容量。如果我們隊(duì)列容量較小,通常需要把maximumPoolSize設(shè)置大一些,這樣CPU使用率會(huì)高一些。但是如果線程池容量設(shè)置過大,在提交人物數(shù)量過多的情況下,并發(fā)量會(huì)增加,那么線程間資源調(diào)度就是一個(gè)需要考慮的問題,反而會(huì)降低處理的吞吐量。

線程池狀態(tài)

當(dāng)我們初始化一個(gè)線程池之后,通常有上面幾種狀態(tài)。

running:可以接受新提交的任務(wù),也能處理阻塞隊(duì)列中的任務(wù)。

shutdown:關(guān)閉狀態(tài),當(dāng)一個(gè)線程池實(shí)例處于shutdown狀態(tài)時(shí),不能再接收新提交的任務(wù),但卻可以繼續(xù)處理阻塞隊(duì)列中已經(jīng)保存的任務(wù)。

stop:也不能接收新的任務(wù),也不處理隊(duì)列中的任務(wù)。會(huì)中斷正在處理的線程任務(wù)。

tidying:所有任務(wù)都已經(jīng)終止了,沒有活動(dòng)中的線程。當(dāng)線程池進(jìn)行該狀態(tài)時(shí)候,會(huì)執(zhí)行鉤子方法terminated() 。

ThreadPoolExecutor中的方法

  • execute():提交任務(wù),交給線程池執(zhí)行
  • submit():提交任務(wù),能夠返回執(zhí)行結(jié)果 相當(dāng)于execute+Future
  • shutdown():關(guān)閉線程池,等待任務(wù)都執(zhí)行完
  • shutdownNow():關(guān)閉線程池,不等待任務(wù)執(zhí)行完
  • getTaskCount():線程池已執(zhí)行和未執(zhí)行的任務(wù)總數(shù)
  • getCompletedTaskCount():已完成的任務(wù)數(shù)量
  • getPoolSize():線程池當(dāng)前的線程數(shù)量
  • getActiveCount():當(dāng)前線程池中正在執(zhí)行任務(wù)的線程數(shù)量
  • Executors框架接口

    • Executors.newCachedThreadPool:創(chuàng)建一個(gè)可緩存的線程池,如果線程池的長(zhǎng)度超過了線程的需要,可以靈活回收空閑線程,如果沒有回收的,可以新建線程
    • Executors.newFixedThreadPool:創(chuàng)建一個(gè)定長(zhǎng)的線程池,可以控制線程的最大并發(fā)數(shù),超出的線程會(huì)在隊(duì)列中等待
    • Executors.newScheduledThreadPool:也是創(chuàng)建一個(gè)定長(zhǎng)的線程池。支持定時(shí)以及周期性的任務(wù)執(zhí)行。
    • Executors.newSingleThreadExecutor:創(chuàng)建一個(gè)單線程的線程池,會(huì)用唯一的工作線程來執(zhí)行任務(wù)。保證所有任務(wù)按照指定順序去執(zhí)行(先入先出等)。

    ?Executors.newCachedThreadPool示例代碼:

    @Slf4j public class ThreadPoolExample1 {public static void main(String[] args) {ExecutorService executorService = Executors.newCachedThreadPool();for (int i = 0; i< 10; i++){final int index = i;executorService.execute(new Runnable() {@Overridepublic void run() {log.info("task:{}", index);}});}//一定要關(guān)閉線程池,否則程序不結(jié)束executorService.shutdown();} }

    Executors.newSingleThreadExecutor示例代碼:

    @Slf4j public class ThreadPoolExample3 {public static void main(String[] args) {ExecutorService executorService = Executors.newSingleThreadExecutor();for (int i = 0; i< 10; i++){final int index = i;executorService.execute(new Runnable() {@Overridepublic void run() {log.info("task:{}", index);}});}//一定要關(guān)閉線程池,否則程序不結(jié)束executorService.shutdown();} }

    輸出結(jié)果:

    17:08:16.870 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:0 17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:1 17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:2 17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:3 17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:4 17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:5 17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:6 17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:7 17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:8 17:08:16.875 [pool-1-thread-1] INFO com.vincent.example.threadPool.ThreadPoolExample3 - task:9

    相當(dāng)于單線程按順序執(zhí)行。??

    Executors.newScheduledThreadPool代碼示例:

    @Slf4j public class ThreadPoolExample4 {public static void main(String[] args) {ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);scheduledExecutorService.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {log.warn("schedule run");}},1, 3, TimeUnit.SECONDS);//這里不需要關(guān)閉線程池//scheduledExecutorService.shutdown();} }

    上面目的是:延遲1秒后,每個(gè)三秒執(zhí)行一次任務(wù),由于這個(gè)任務(wù)時(shí)不定的執(zhí)行,因此這里不應(yīng)該關(guān)閉線程池。如果需要關(guān)閉線程池的話,可以設(shè)置一個(gè)觸發(fā)條件來關(guān)閉。類似于Timer類:

    @Slf4j public class ThreadPoolExample4 {public static void main(String[] args) {Timer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {log.warn("timer run");}}, new Date(), 5*1000);} }

    線程池合理配置

    • CPU密集型任務(wù),就需要盡量壓榨CPU,參考值可以設(shè)置為NCPU+1
    • 如果是IO密集型任務(wù),參考值可以設(shè)置為2*NCPU

    ????我們只用線程池主要是為了重用存在的線程,減少對(duì)象創(chuàng)建消亡,能有效控制最大線程并發(fā)數(shù),可以避免過多的資源競(jìng)爭(zhēng)和阻塞,也可以定時(shí)執(zhí)行單線程與控制線程的執(zhí)行性能比較好。?這不代表線程池應(yīng)該隨時(shí)隨地用,一定要根據(jù)自己的實(shí)際場(chǎng)景來分析使用參數(shù)配置

    總結(jié)

    以上是生活随笔為你收集整理的java高并发(十八)线程池的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。