黄色网址大全免费-黄色网址你懂得-黄色网址你懂的-黄色网址有那些-免费超爽视频-免费大片黄国产在线观看

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

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

更新時間:2023-01-10 15:11:18 來源:動力節(jié)點 瀏覽1264次

什么是線程池

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

為什么要使用線程池

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

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

java線程池面試題

線程池有哪些作用

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

提高響應速度:任務到達時,無需等待線程創(chuàng)建即可立即執(zhí)行。

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

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

線程池的創(chuàng)建方式

分為以下幾種創(chuàng)建方式:

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

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

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

Executors.newSingleThreadExecutor():單例線程池

底層都是基于 ThreadPoolExecutor 構造函數(shù)封裝

如何實現(xiàn)復用

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

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

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

正在運行的線程從并發(fā)隊列中獲取任務執(zhí)行從而實現(xiàn)線程復用的問題。

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

java線程池面試題

線程池核心點:復用機制

提前創(chuàng)建好固定的線程一直在運行狀態(tài)---死循環(huán)實現(xiàn)。

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

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

簡單實現(xiàn)代碼如下:

/**
 * @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 或者隊列中有未執(zhí)行完成的任務
            while(isRun || runnableList.size()>0) {
                Runnable runnable = runnableList.poll();
                // 如果不為空 ,執(zhí)行
                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核心參數(shù)

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

maximumPoolSize:最大線程數(shù),線程池允許創(chuàng)建的最大線程數(shù)。

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

unit:keepAliveTime 的時間單位。

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

threadFactory :線程池內部創(chuàng)建線程所用的工廠。

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

其他相關總結

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

線程池底層 ThreadPoolExecutor 底層實現(xiàn)原理

2.1. 當線程數(shù)小于核心線程數(shù)時,創(chuàng)建線程。

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

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

2.3.1. 如果線程數(shù)小于最大線程數(shù),創(chuàng)建線程。

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

如果隊列滿了,且任務總數(shù)>最大線程數(shù)則當前線程走拒絕策略。可自定義拒絕異常,將該任務緩存到Redis、本地文件、mysql中,后期項目啟動實現(xiàn)補償。

拒絕策略有以下幾種:

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

4.2. CallerRunsPolicy:執(zhí)行任務。

4.3. DiscardPolicy 忽視

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

4.5. 實現(xiàn) RejectedExecutionHandler 接口,可自定義處理器。

如何合理配置參數(shù)

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

5.1 CPU密集型:

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

5.2 IO密集型

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

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

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

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

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

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 偷偷狠狠的日日高清完整视频 | 久久最新免费视频 | 波多野结衣久久 | 欧美成人亚洲国产精品 | 久久99精品久久久久久秒播放器 | 曰曰碰天天碰国产 | 天天操天天射天天 | 国产免费无遮挡精品视频 | 日韩在线视屏 | 婷婷成人丁香五月综合激情 | 亚洲欧美一区二区久久 | 日本无翼乌全彩无遮挡动漫 | 免费在线观看黄 | 成年黄网站色大免费全看 | 黄色片一级片 | 亚洲国产成人在线 | 久久夜夜肉肉热热日日 | 美女黄色片网站 | 成人国产精品视频频 | 亚洲一区精品在线 | 中文字幕35页 | 成人在线免费播放 | 一区二区三区四区精品视频 | 羞羞视频网站免费 | 成年人在线免费观看 | 在线日韩麻豆一区 | 日韩中文字幕精品 | 综合在线视频精品专区 | 日韩色在线| 77成人影视 | 在线观看国产一区二区三区99 | 美国fx性欧美xxxx | 最近韩国日本高清免费观看 | 久久久久久久久97 | 国产无限免费观看黄网站 | 欧美激情免费a视频 | 亚洲国产福利精品一区二区 | 日本动漫看片黄a免费看 | 亚洲国产一区二区三区最新 | h网站在线播放 | 成人18网址在线观看 |