大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 學習攻略 職業指南 大廠HR經常會問到的Java線程池面試題

大廠HR經常會問到的Java線程池面試題

更新時間:2023-01-10 15:11:18 來源:動力節點 瀏覽1249次

什么是線程池

線程池和數據庫連接池非常類似,可以統一管理和維護線程,減少沒有必要的開銷。

為什么要使用線程池

因為在項目開發過程中頻繁的開啟線程或者停止線程,線程需要重新被CPU從就緒狀態調度到運行狀態,需要發生CPU的上下文切換,效率非常低。

線程的生命周期如下圖所示:

java線程池面試題

線程池有哪些作用

降低資源消耗:通過池化技術重復利用已創建好的線程,降低線程創建和銷毀造成的損耗。

提高響應速度:任務到達時,無需等待線程創建即可立即執行。

提高線程的可管理性:線程是稀缺資源,如果無限制創建,不僅會消耗系統資源,還會因為線程的不合理分布導致資源調度失衡,降低系統的穩定性。使用線程池可以進行統一的分配、調優和監控。

提供更多強大的功能:線程池具備可拓展性,允許開發人員向其中增加更多的功能。比如延遲定時線程池 ScheduledThreadPoolExecutor ,就允許任務延期執行或定期執行。

線程池的創建方式

分為以下幾種創建方式:

Executors.newCachedThreadPool():可緩存線程池

Executors.newFixedThreadPool():可定長度,限制最大線程數

Executors.newScheduledThreadPool():可定時線程池

Executors.newSingleThreadExecutor():單例線程池

底層都是基于 ThreadPoolExecutor 構造函數封裝

如何實現復用

本質思想:創建一個線程,不會立馬體質或者銷毀,而是一直實現復用。

提前創建固定大小的線程一直保持正在運行的狀態(可能會非常消耗CPU資源)。

當需要線程執行任務,將該任務提交緩存在并發隊列中,如果緩存隊列滿了,則會執行拒絕策略。

正在運行的線程從并發隊列中獲取任務執行從而實現線程復用的問題。

線程池底層原理如下圖所示:

java線程池面試題

線程池核心點:復用機制

提前創建好固定的線程一直在運行狀態---死循環實現。

提交的線程任務緩存到一個并發隊列集合中,交給我們正在運行的線程執行。

正在運行的線程就從隊列中獲取該任務執行。

簡單實現代碼如下:

/**
 * @author zfl_a
 * @date 2021/3/20
 * @project multi-thread
 */
public class CustExcutors {

    // 存放線程任務
    public BlockingDeque<Runnable> runnableList ;

    // 停止線程標識位
    private volatile Boolean isRun = true ;

    /**
     * 初始化
     * @param dequeSize 隊列容器大小
     * @param threadCount 線程池大小
     */
    public CustExcutors(int dequeSize,int threadCount){
        runnableList = new LinkedBlockingDeque<>(dequeSize);
        for (int i=0;i<threadCount;i++) {
            WorkThread workThread = new WorkThread();
            workThread.start();
        }
    }

    public void execute(Runnable runnable){
        runnableList.offer(runnable);
    }

    class WorkThread extends Thread {

        @Override
        public void run (){
            // 標識位位true 或者隊列中有未執行完成的任務
            while(isRun || runnableList.size()>0) {
                Runnable runnable = runnableList.poll();
                // 如果不為空 ,執行
                if(runnable!=null) {
                    runnable.run();
                }
            }
        }
    }

    public static void main(String[] args) {
        CustExcutors custExcutors = new CustExcutors(10,2);
        for (int x=0;x<10;x++) {
            final int i = x ;
            custExcutors.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"----"+i);
                }
            });
        }
        // 停止線程
        custExcutors.isRun=false;
    }
}

運行結果:只有兩個線程在運行任務

java線程池面試題

ThreadPoolExecutor核心參數

corePoolSize:核心線程數量,一直正在保持運行的線程。

maximumPoolSize:最大線程數,線程池允許創建的最大線程數。

keepAliveTime:超出 corePoolSize 后創建的線程存活時間(當超過核心線程數后,又沒有線程任務執行,達到該存活時間后,停止該線程)。

unit:keepAliveTime 的時間單位。

workQueue:任務隊列,用于保持待執行的任務。

threadFactory :線程池內部創建線程所用的工廠。

handler:任務無法執行時的處理器(當任務被拒絕時)。

其他相關總結

線程池不會一直在運行狀態。假設配置核心線程數 corePoolSize 為2 ,最大線程數 maximumPoolSize 為5,我們可以通過 corePoolSize 核心線程數后創建的線程的存活時間例如為60s,在60s內沒有線程任務執行,則會停止該線程。

線程池底層 ThreadPoolExecutor 底層實現原理

2.1. 當線程數小于核心線程數時,創建線程。

2.2. 當線程數大于等于核心線程數,且任務隊列未滿時,將任務放入任務隊列。

2.3. 當線程數大于等于核心線程數,且任務隊列已滿,有以下兩種情況。

2.3.1. 如果線程數小于最大線程數,創建線程。

2.3.2. 如果線程數等于最大線程數,拋出異常,拒絕任務。

如果隊列滿了,且任務總數>最大線程數則當前線程走拒絕策略??勺远x拒絕異常,將該任務緩存到Redis、本地文件、mysql中,后期項目啟動實現補償。

拒絕策略有以下幾種:

4.1. AbortPolicy:丟棄任務,拋出運行時異常。

4.2. CallerRunsPolicy:執行任務。

4.3. DiscardPolicy 忽視

4.4. DiscardOldestPolicy:從隊列中剔除最先進入隊列(最后一個執行)的任務。

4.5. 實現 RejectedExecutionHandler 接口,可自定義處理器。

如何合理配置參數

自定義線程池就需要我們自己配置最大線程數 maximumPoolSize ,為了高效的并發運行,這時需要看我們的業務是IO密集型還是CPU密集型。

5.1 CPU密集型:

CPU密集的意思是該任務需要最大的運算,而沒有阻塞,CPU一直全速運行。CPU密集任務只有在真正的多核CPU上才能得到加速(通過多線程)。而在單核CPU上,無論你開幾個模擬的多線程該任務都不可能得到加速,因為CPU總的運算能力就那么多。

5.2 IO密集型

IO密集型,即該任務需要大量的IO,即大量的阻塞。在單線程上運行IO密集型的任務會導致大量的CPU運算能力浪費在等待。所以在IO密集型任務中使用多線程可以大大的加速程序運行,即使在單核CPU上這種加速主要就是利用了被浪費掉的阻塞時間。

IO 密集型時,大部分線程都阻塞,故需要多配制線程數。公式為:

CPU核數*2
CPU核數/(1-阻塞系數) 阻塞系數在0.8~0.9之間
查看CPU核數:
System.out.println(Runtime.getRuntime().availableProcessors());

以上就是“大廠HR經常會問到的Java線程池面試題”,你能回答上來嗎?如果想要了解更多的Java面試題相關內容,可以關注動力節點Java官網。

提交申請后,顧問老師會電話與您溝通安排學習

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 欧美影院| 精品久久亚洲 | 精品无人区乱码1区2区3区在线 | 中文字幕一区二区三 | 377p亚洲欧洲日本大胆色噜噜 | 亚洲免费高清 | 国产亚洲自拍一区 | 狠狠色噜噜狠狠狠狠网站视频 | 亚洲欧美国产日产综合不卡 | 午夜剧j| 国产萝控精品福利视频免费 | 日韩欧美亚洲综合久久影院d3 | 日韩精品久久不卡中文字幕 | cao美女视频网站在线观看 | 国产精品美女免费视频大全 | 免费国产成人午夜在线观看 | 欧美日韩不卡视频 | 99精品久久精品一区二区 | 亚洲国产国产综合一区首页 | 久久精品男人影院 | 国产一区二区不卡 | 狠狠色狠狠色综合日日32 | 午夜国产精品福利在线观看 | 日韩一区二区三 | 五月婷婷在线视频观看 | 亚洲高清免费视频 | 久久男人资源站 | 国产精品美女久久久久久 | 一及黄色毛片 | 天天操夜夜操天天操 | 欧美一级视频在线观看 | 久亚洲精品不子伦一区 | 九九热在线视频免费观看 | 四房快播| 干一干操一操 | 久久综合中文字幕 | 亚洲一区二区视频 | 久久中文字幕免费视频 | 欧美国产一区二区三区 | 四虎国产精品免费入口 | 在线观看欧美视频 |