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

Java中的線程池ThreadPoolExecutor深入解析

 更新時間:2023年11月09日 09:47:34   作者:莫輕言舞  
這篇文章主要介紹了Java中的線程池ThreadPoolExecutor深入解析,線程池,thread pool,是一種線程使用模式,線程池維護(hù)著多個線程,等待著監(jiān)督管理者分配可并發(fā)執(zhí)行的任務(wù),需要的朋友可以參考下

1.什么是線程池?

線程池,thread pool,是一種線程使用模式,線程池維護(hù)著多個線程,等待著監(jiān)督管理者分配可并發(fā)執(zhí)行的任務(wù)。

通俗來說,就是可管理和維護(hù)以及分配線程的“池子”。

2.為什么使用線程池?

為了減少創(chuàng)建和銷毀線程的次數(shù),讓每個線程都可以多次的使用,可以根據(jù)系統(tǒng)情況調(diào)整線程的數(shù)量,防止消耗過多內(nèi)存。在實際使用中,服務(wù)器在創(chuàng)建和銷毀線程上花費(fèi)的時間和消耗的系統(tǒng)資源都相當(dāng)大,使用線程池就可以優(yōu)化。 線程池主要用來解決線程生命周期開銷問題和資源不足問題。通過對多個任務(wù)重復(fù)使用線程,線程創(chuàng)建的開銷就被分?jǐn)偟搅硕鄠€任務(wù)上了,而且由于在請求到達(dá)時線程已經(jīng)存在,所以消除了線程創(chuàng)建所帶來的延遲。這樣,就可以立即為請求服務(wù),使用應(yīng)用程序響應(yīng)更快。另外,通過適當(dāng)?shù)恼{(diào)整線程中的線程數(shù)目可以防止出現(xiàn)資源不足的情況。

通俗來說,就是為了優(yōu)化線程的內(nèi)存開銷。

3.線程池的核心參數(shù)

public ThreadPoolExecutor(int corePoolSize,//核心線程數(shù)
                          int maximumPoolSize,//最大線程數(shù)
                          long keepAliveTime,//線程空閑時間
                          TimeUnit unit,//時間單位
                          BlockingQueue<Runnable> workQueue,//任務(wù)隊列
                          ThreadFactory threadFactory,//線程工廠
                          RejectedExecutionHandler handler//拒絕策略) 
{
    ...
}

4.線程池的執(zhí)行順序

線程池按以下行為執(zhí)行任務(wù)

  • 當(dāng)線程數(shù)小于核心線程數(shù)時,創(chuàng)建線程。
  • 當(dāng)線程數(shù)大于等于核心線程數(shù),且任務(wù)隊列未滿時,將任務(wù)放入任務(wù)隊列。
  • 當(dāng)線程數(shù)大于等于核心線程數(shù),且任務(wù)隊列已滿,若線程數(shù)小于最大線程數(shù),創(chuàng)建線程。
  • 若線程數(shù)等于最大線程數(shù),則執(zhí)行拒絕策略

5.線程池的參數(shù)詳解

(a)、corePoolSize

核心線程數(shù),默認(rèn)為1。

設(shè)置規(guī)則:

CPU密集型(CPU密集型也叫計算密集型,指的是運(yùn)算較多,cpu占用高,讀/寫I/O(硬盤/內(nèi)存)較少):corePoolSize = CPU核數(shù) + 1IO密集型(與cpu密集型相反,系統(tǒng)運(yùn)作,大部分的狀況是CPU在等I/O (硬盤/內(nèi)存) 的讀/寫操作,此時CPU Loading并不高。):corePoolSize = CPU核數(shù) * 2

(b)、maximumPoolSize最大線程數(shù),默認(rèn)為Integer.MAX_VALUE一般設(shè)置為和核心線程數(shù)一樣

(c)、keepAliveTime線程空閑時間,默認(rèn)為60s,一般設(shè)置為默認(rèn)60s

(d)、unit時間單位,默認(rèn)為秒

(e)、workQueue隊列,當(dāng)線程數(shù)目超過核心線程數(shù)時用于保存任務(wù)的隊列。(BlockingQueue workQueue)此隊列僅保存實現(xiàn)Runnable接口的任務(wù)。(因為線程池的底層BlockingQueue的泛型為Runnable)

(1)無界隊列

隊列大小無限制,常用的為無界的LinkedBlockingQueue,使用該隊列作為阻塞隊列時要尤其當(dāng)心,當(dāng)任務(wù)耗時較長時可能會導(dǎo)致大量新任務(wù)在隊列中堆積最終導(dǎo)致OOM。閱讀代碼發(fā)現(xiàn),Executors.newFixedThreadPool 采用就是 LinkedBlockingQueue,而博主踩到的就是這個坑,當(dāng)QPS很高,發(fā)送數(shù)據(jù)很大,大量的任務(wù)被添加到這個無界LinkedBlockingQueue 中,導(dǎo)致cpu和內(nèi)存飆升服務(wù)器掛掉。

當(dāng)然這種隊列,maximumPoolSize 的值也就無效了。當(dāng)每個任務(wù)完全獨(dú)立于其他任務(wù),即任務(wù)執(zhí)行互不影響時,適合于使用無界隊列;例如,在 Web 頁服務(wù)器中。這種排隊可用于處理瞬態(tài)突發(fā)請求,當(dāng)命令以超過隊列所能處理的平均數(shù)連續(xù)到達(dá)時,此策略允許無界線程具有增長的可能性。

(2)有界隊列

當(dāng)使用有限的 maximumPoolSizes 時,有界隊列有助于防止資源耗盡,但是可能較難調(diào)整和控制。常用的有兩類,一類是遵循FIFO原則的隊列如ArrayBlockingQueue,另一類是優(yōu)先級隊列如PriorityBlockingQueue。PriorityBlockingQueue中的優(yōu)先級由任務(wù)的Comparator決定。
使用有界隊列時隊列大小需和線程池大小互相配合,線程池較小有界隊列較大時可減少內(nèi)存消耗,降低cpu使用率和上下文切換,但是可能會限制系統(tǒng)吞吐量。

(3)同步移交隊列

如果不希望任務(wù)在隊列中等待而是希望將任務(wù)直接移交給工作線程,可使用SynchronousQueue作為等待隊列。SynchronousQueue不是一個真正的隊列,而是一種線程之間移交的機(jī)制。要將一個元素放入SynchronousQueue中,必須有另一個線程正在等待接收這個元素。只有在使用無界線程池或者有飽和策略時才建議使用該隊列。

(f)、threadFactory

線程工廠,用來創(chuàng)建線程。

為了統(tǒng)一在創(chuàng)建線程時設(shè)置一些參數(shù),如是否守護(hù)線程,線程一些特性等,如優(yōu)先級。通過這個TreadFactory創(chuàng)建出來的線程能保證有相同的特性。

它是一個接口類,而且方法只有一個,就是創(chuàng)建一個線程。

如果沒有另外說明,則在同一個ThreadGroup 中一律使用Executors.defaultThreadFactory() 創(chuàng)建線程,并且這些線程具有相同的NORM_PRIORITY 優(yōu)先級和非守護(hù)進(jìn)程狀態(tài)。

通過提供不同的 ThreadFactory,可以改變線程的名稱、線程組、優(yōu)先級、守護(hù)進(jìn)程狀態(tài),等等。

如果從newThread 返回 null 時ThreadFactory 未能創(chuàng)建線程,則執(zhí)行程序?qū)⒗^續(xù)運(yùn)行,但不能執(zhí)行任何任務(wù)。

(g)、handler

拒絕策略,默認(rèn)是AbortPolicy,會拋出異常。

當(dāng)線程數(shù)已經(jīng)達(dá)到maxPoolSize,且隊列已滿,會拒絕新任務(wù)。

當(dāng)線程池被調(diào)用shutdown()后,會等待線程池里的任務(wù)執(zhí)行完畢再shutdown。如果在調(diào)用shutdown()和線程池真正shutdown之間提交任務(wù),會拒絕新任務(wù)。

  • AbortPolicy 丟棄任務(wù),拋運(yùn)行時異常。
  • CallerRunsPolicy 由當(dāng)前調(diào)用的任務(wù)線程執(zhí)行任務(wù)。
  • DiscardPolicy 忽視,什么都不會發(fā)生。
  • DiscardOldestPolicy 從隊列中踢出最先進(jìn)入隊列(最后一個執(zhí)行)的任務(wù)。

6.ThreadPoolExecutor和spring封裝的ThreadPoolTaskExecutor案例

ThreadPoolExecutor是Java的線程池 ThreadPoolTaskExecutor是spring封裝的線程池

package com.thgy.bc.common.config;
 
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 
import java.util.concurrent.*;
 
@Slf4j
@Configuration
public class ThreadPoolConfig {
    @Bean
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        int i = Runtime.getRuntime().availableProcessors();
        //核心線程數(shù)目
        executor.setCorePoolSize(i * 2);
        //指定最大線程數(shù)
        executor.setMaxPoolSize(i * 2);
        //隊列中最大的數(shù)目
        executor.setQueueCapacity(i * 2 * 10);
        //線程名稱前綴
        executor.setThreadNamePrefix("ThreadPoolTaskExecutor-");
        //rejection-policy:當(dāng)pool已經(jīng)達(dá)到max size的時候,如何處理新任務(wù)
        //CALLER_RUNS:不在新線程中執(zhí)行任務(wù),而是由調(diào)用者所在的線程來執(zhí)行
        //對拒絕task的處理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //當(dāng)調(diào)度器shutdown被調(diào)用時等待當(dāng)前被調(diào)度的任務(wù)完成
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //線程空閑后的最大存活時間
        executor.setKeepAliveSeconds(60);
        //加載
        executor.initialize();
        log.info("初始化線程池成功");
        return executor;
    }
 
    @Bean
    public ThreadPoolExecutor threadPoolExecutor() {
        //獲取cpu核心數(shù)
        int i = Runtime.getRuntime().availableProcessors();
        //核心線程數(shù)
        int corePoolSize = i * 2;
        //最大線程數(shù)
        int maximumPoolSize = i * 2;
        //線程無引用存活時間
        long keepAliveTime = 60;
        //時間單位
        TimeUnit unit = TimeUnit.SECONDS;
        //任務(wù)隊列,接收一個整型的參數(shù),這個整型參數(shù)指的是隊列的長度,
        //ArrayBlockingQueue(int,boolean),boolean類型的參數(shù)是作為可重入鎖的參數(shù)進(jìn)行初始化,默認(rèn)false,另外初始化了notEmpty、notFull兩個信號量。
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue(i * 2 * 10);
        //1. 同步阻塞隊列 (put,take),直接提交。直接提交策略表示線程池不對任務(wù)進(jìn)行緩存。新進(jìn)任務(wù)直接提交給線程池,當(dāng)線程池中沒有空閑線程時,創(chuàng)建一個新的線程處理此任務(wù)。
        // 這種策略需要線程池具有無限增長的可能性。實現(xiàn)為:SynchronousQueue
        //2. 有界隊列。當(dāng)線程池中線程達(dá)到corePoolSize時,新進(jìn)任務(wù)被放在隊列里排隊等待處理。有界隊列(如ArrayBlockingQueue)有助于防止資源耗盡,
        // 但是可能較難調(diào)整和控制。隊列大小和最大池大小可能需要相互折衷:使用大型隊列和小型池可以最大限度地降低 CPU 使用率、操作系統(tǒng)資源和上下文切換開銷,
        // 但是可能導(dǎo)致人工降低吞吐量。如果任務(wù)頻繁阻塞(例如,如果它們是 I/O 邊界),則系統(tǒng)可能為超過您許可的更多線程安排時間。使用小型隊列通常要求較大的池大小,
        // CPU 使用率較高,但是可能遇到不可接受的調(diào)度開銷,這樣也會降低吞吐量。
        //3. 無界隊列。使用無界隊列(例如,不具有預(yù)定義容量的 LinkedBlockingQueue)將導(dǎo)致在所有 corePoolSize 線程都忙時新任務(wù)在隊列中等待。
        // 這樣,創(chuàng)建的線程就不會超過 corePoolSize。(因此,maximumPoolSize 的值也就無效了。)當(dāng)每個任務(wù)完全獨(dú)立于其他任務(wù),即任務(wù)執(zhí)行互不影響時,
        // 適合于使用無界隊列;例如,在 Web 頁服務(wù)器中。這種排隊可用于處理瞬態(tài)突發(fā)請求,當(dāng)命令以超過隊列所能處理的平均數(shù)連續(xù)到達(dá)時,此策略允許無界線程具有增長的可能性。
 
        //線程工廠
        //defaultThreadFactory()
        //返回用于創(chuàng)建新線程的默認(rèn)線程工廠。
        //privilegedThreadFactory()
        //返回一個用于創(chuàng)建與當(dāng)前線程具有相同權(quán)限的新線程的線程工廠。
        ThreadFactory threadFactory =Executors.defaultThreadFactory();
        //拒絕執(zhí)行處理器
        RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();
        //創(chuàng)建線程池
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
        return threadPoolExecutor;
    }
}
 

7.jdk自帶的四種線程池創(chuàng)建方式

// 第一種線程池:固定個數(shù)的線程池,可以為每個CPU核綁定一定數(shù)量的線程數(shù)
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(processors * 2);
// 緩存線程池,無上限
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
// 單一線程池,永遠(yuǎn)會維護(hù)存在一條線程
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
// 固定個數(shù)的線程池,可以執(zhí)行延時任務(wù),也可以執(zhí)行帶有返回值的任務(wù)。
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);

8.調(diào)用線程池的線程案例

public List<AccountRecordVO> requestTest() throws ExecutionException, InterruptedException {
        List<String> ids = Lists.newArrayList();
        ids.add("1");
        ids.add("2");
        ids.add("3");
        ids.add("4");
        //有返回值的情況,定義接收返回值
        List<AccountRecordVO> futureList2 = Lists.newArrayList();
        //分布式計數(shù)器,若業(yè)務(wù)不需要則可以不定義
        CountDownLatch countDownLatch = new CountDownLatch(ids.size());
        for (String id : ids) {
            //調(diào)用線程池的線程執(zhí)行任務(wù)
            threadPoolTaskExecutor.submit(new Runnable() {
                @Override
                public void run() {
                    test(Lists.newArrayList(id),futureList2);
                    //計數(shù)器-1
                    countDownLatch.countDown();
                }
            });
        }
        //await阻塞,直到計數(shù)器為0
        countDownLatch.await();
        System.out.println("主線程"+"====");
        return futureList2;
    }
 
    public List<AccountRecordVO> test(List<String> ids, List<AccountRecordVO> list2){
        //隨便寫的業(yè)務(wù)邏輯代碼,無實際意義,僅作演示
        System.out.println("線程體" + "====");
        List<AccountRecordVO> accountRecordVOS = Lists.newArrayList();
        int i = 0;
        AccountRecordVO accountRecordVO = new AccountRecordVO();
        accountRecordVO.setUserId("123");
        accountRecordVO.setAmount(12333);
        for (String id : ids){
            accountRecordVOS.add(accountRecordVO);
            list2.add(accountRecordVO);
        }
        try{
            Thread.sleep(Long.valueOf("1000"));
        }catch (Exception e){
            log.error(e.getMessage());
        }
        System.out.println("線程體結(jié)束" + "====");
        return accountRecordVOS;
    }

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

相關(guān)文章

  • Springboot 整合 Java DL4J 實現(xiàn)時尚穿搭推薦系統(tǒng)(實例代碼)

    Springboot 整合 Java DL4J 實現(xiàn)時尚穿搭推薦系統(tǒng)(實例代碼)

    本文介紹了如何使用SpringBoot和JavaDeeplearning4j框架搭建一個時尚穿搭推薦系統(tǒng),文章詳細(xì)闡述了系統(tǒng)的技術(shù)架構(gòu)、數(shù)據(jù)集格式、Maven依賴配置、模型訓(xùn)練和預(yù)測代碼實現(xiàn),以及單元測試和預(yù)期輸出結(jié)果
    2024-10-10
  • 如何在Java中創(chuàng)建線程通信的四種方式你知道嗎

    如何在Java中創(chuàng)建線程通信的四種方式你知道嗎

    開發(fā)中不免會遇到需要所有子線程執(zhí)行完畢通知主線程處理某些邏輯的場景?;蛘呤蔷€程 A 在執(zhí)行到某個條件通知線程 B 執(zhí)行某個操作。下面我們來一起學(xué)習(xí)如何解決吧
    2021-09-09
  • SpringBoot項目中出現(xiàn)不同端口跨域問題的解決方法

    SpringBoot項目中出現(xiàn)不同端口跨域問題的解決方法

    這篇文章主要介紹了SpringBoot項目中出現(xiàn)不同端口跨域問題的解決方法,文中介紹了兩種解決方法,并給出了詳細(xì)的代碼供大家參考,具有一定的參考價值,需要的朋友可以參考下
    2024-03-03
  • Mybatis如何解決sql中l(wèi)ike通配符模糊匹配問題

    Mybatis如何解決sql中l(wèi)ike通配符模糊匹配問題

    這篇文章主要介紹了Mybatis如何解決sql中l(wèi)ike通配符模糊匹配問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 淺談Maven包沖突的原理及解決方法

    淺談Maven包沖突的原理及解決方法

    這篇文章主要介紹了淺談Maven包沖突的原理及解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • java多線程模擬實現(xiàn)售票功能

    java多線程模擬實現(xiàn)售票功能

    這篇文章主要為大家詳細(xì)介紹了java多線程模擬實現(xiàn)售票功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 總結(jié)Java常用到的六個加密技術(shù)和代碼

    總結(jié)Java常用到的六個加密技術(shù)和代碼

    大家要記住現(xiàn)代密碼學(xué)最重要的原則柯克霍夫原則:數(shù)據(jù)的安全基于密鑰而不是算法的保密。也就是說即使密碼系統(tǒng)的任何細(xì)節(jié)已為人悉知,只要密匙未洩漏,它也應(yīng)是安全的。這篇文章給大家介紹了6個常用的加密技術(shù)和代碼。
    2016-07-07
  • 詳解在SpringBoot中@Transactional事物操作和事物無效問題排查

    詳解在SpringBoot中@Transactional事物操作和事物無效問題排查

    這篇文章主要介紹了詳解在SpringBoot中@Transactional事物操作和事物無效問題排查,本文詳細(xì)的介紹了SpringBoot中集成使用@Transactional注解操作事物以及事物開啟后無效的問題排查,需要的朋友可以參考下
    2021-06-06
  • Java泛型的繼承和實現(xiàn)操作示例

    Java泛型的繼承和實現(xiàn)操作示例

    這篇文章主要介紹了Java泛型的繼承和實現(xiàn)操作,結(jié)合實例形式分析了java泛型類的繼承以及泛型接口的實現(xiàn)相關(guān)操作技巧,需要的朋友可以參考下
    2019-08-08
  • idea編譯器使用git拉取、提交非常慢的原因分析及解決

    idea編譯器使用git拉取、提交非常慢的原因分析及解決

    換電腦后IDEA使用Git操作卡頓,經(jīng)排查發(fā)現(xiàn)殺毒軟件誤判runnerw.exe為病毒,解決方法:重命名該文件或關(guān)閉Windows實時保護(hù),重啟后Git速度顯著提升
    2025-09-09

最新評論

浙江省| 如东县| 虎林市| 涪陵区| 黄陵县| 七台河市| 南充市| 渝中区| 开原市| 凌海市| 凤城市| 西盟| 武冈市| 济南市| 获嘉县| 康平县| 巴彦县| 西乡县| 岳西县| 新和县| 德化县| 闽侯县| 东方市| 文昌市| 固镇县| 宜宾市| 潞城市| 鄂州市| 平安县| 富裕县| 香港| 鹿泉市| 顺昌县| 汝城县| 容城县| 景东| 大荔县| 资溪县| 什邡市| 邵武市| 迁西县|