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

Java線程池八股及實(shí)現(xiàn)過程

 更新時(shí)間:2026年01月30日 10:27:00   作者:小樓v  
線程池的八股包括線程池的核心參數(shù)、執(zhí)行原理、拒絕策略、阻塞隊(duì)列、核心線程數(shù)的確定、線程池種類、不建議使用Executors創(chuàng)建線程池的原因、ThreadLocal的理解及ThreadLocal的內(nèi)存泄露問題,展示了線程池的運(yùn)行機(jī)制,本文介紹Java線程池八股及實(shí)現(xiàn),感興趣的朋友一起看看吧

線程池的八股

1、說一下線程池的核心參數(shù)?

ThreadPoolExecutor線程池的核心參數(shù)有7個(gè),1.核心線程數(shù)目(corePoolSize)、2.最大線程數(shù)目(maximumPoolSize),最大線程數(shù)目=核心線程+臨時(shí)線程、3.生存時(shí)間(keepAliveTime),是臨時(shí)線程的生存時(shí)間,生存時(shí)間內(nèi)沒有新任務(wù),臨時(shí)線程會(huì)釋放、4.時(shí)間單位(unit)、5.阻塞隊(duì)列(workQueue),當(dāng)核心線程滿了之后新來的任務(wù)會(huì)進(jìn)入隊(duì)列排隊(duì),隊(duì)列滿后會(huì)創(chuàng)建臨時(shí)線程執(zhí)行任務(wù)、6.線程工廠(threadFactory),定制線程對(duì)象的創(chuàng)建,例如設(shè)置線程名字,是否是守護(hù)線程等、7.拒絕策略(handler),當(dāng)所有線程都在忙,workQueue也放滿時(shí),就會(huì)觸發(fā)拒絕策略。

2、線程池的執(zhí)行原理?

首先提交任務(wù)會(huì)判斷核心線程是否已滿,如果沒滿就正常工作,如果已滿的話就會(huì)判斷這個(gè)阻塞隊(duì)列是否已滿,如果阻塞隊(duì)列沒滿就放入阻塞隊(duì)列等待,如果阻塞隊(duì)列也滿了,就判斷線程數(shù)是否小于最大線程數(shù),如果小于就創(chuàng)建臨時(shí)線程,這時(shí)臨時(shí)線程默認(rèn)是來執(zhí)行新來的任務(wù),而不是執(zhí)行從阻塞隊(duì)列中取出的任務(wù)來執(zhí)行,如果不小于,那就走拒絕策略。

3、拒絕策略有哪些?

拒絕策略有4種,1.AbortPolicy,直接拋異常,默認(rèn)策略。2.CallerRunsPolicy,使用調(diào)用者所在線程來執(zhí)行任務(wù),如主線程main。3.DiscardOldestPolicy,丟棄阻塞隊(duì)列最靠前的任務(wù),來執(zhí)行當(dāng)前任務(wù)。4.DiscardPolicy,直接丟棄任務(wù)。

4、線程池中有哪些常見的阻塞隊(duì)列?

有4種常見的阻塞隊(duì)列,1.ArrayBlockingQueue,基于數(shù)組的有界阻塞隊(duì)列,F(xiàn)IFO。2.LinkedBlockingQueue,基于鏈表的有界阻塞隊(duì)列,F(xiàn)IFO。3.DelayedWorkQueue,優(yōu)先級(jí)阻塞隊(duì)列,保證每次出任務(wù)的是執(zhí)行時(shí)間最靠前的任務(wù)。4.SynchronousQueue,不存儲(chǔ)元素的阻塞隊(duì)列,每次插入操作都要等待一個(gè)移除操作。

5、ArrayBlockingQueue和LinkedBlockingQueue有什么區(qū)別?

LinkedBlockingQueue默認(rèn)是無界的,支持有界,ArrayBlockingQueue強(qiáng)制有界。LinkedBlockingQueue底層是鏈表,ArrayBlockingQueue底層是數(shù)組。LinkedBlockingQueue是懶惰的,創(chuàng)建節(jié)點(diǎn)時(shí)添加數(shù)據(jù),入隊(duì)會(huì)生成新Node,ArrayBlockingQueue是提前初始化Node數(shù)組,Node需要是提前創(chuàng)建好的。LinkedBlockingQueue是兩把鎖,鏈表的頭和尾加鎖,ArrayBlockingQueue是全部一把鎖,一般平時(shí)常用的就是LinkedBlockingQueue。

6、如何確定核心線程數(shù)?

分IO密集型任務(wù)和CPU密集型任務(wù),注:N為CPU核數(shù)。如果并發(fā)不高、執(zhí)行時(shí)間長(zhǎng)的話,設(shè)置為IO密集型任務(wù)核心線程數(shù)就是2N+1;設(shè)置為CPU密集型任務(wù)核心線程數(shù)就是N+1。如果高并發(fā)、任務(wù)執(zhí)行時(shí)間短的話核心線程數(shù)就是N+1,減少線程上下文切換。

7、線程池的種類有哪些?

常見的有4種,1.創(chuàng)建使用固定線程數(shù)的線程池,就是核心線程數(shù)和最大線程數(shù)一樣,沒有臨時(shí)線程,阻塞隊(duì)列是LinkedBlockingQueue。2.單線程化的線程池,核心線程數(shù)和最大線程數(shù)都是1,阻塞隊(duì)列是LinkedBlockingQueue。3.可緩存線程池,核心線程數(shù)為0,只有臨時(shí)線程數(shù),阻塞隊(duì)列是SynchronousQueue,不存儲(chǔ)元素的阻塞隊(duì)列,每次插入操作都要等待一個(gè)移除操作。3.提供了“延遲”和“周期執(zhí)行”功能的ThreadPoolExecutor,可以執(zhí)行延遲任務(wù)的線程池,支持定時(shí)及周期性完成任務(wù)。

8、為什么不建議使用Executors創(chuàng)建線程池?

可能會(huì)堆積大量的請(qǐng)求,創(chuàng)建大量的對(duì)象,導(dǎo)致OOM(內(nèi)存溢出)。

9、談?wù)勀銓?duì)ThreadLocal的理解?

為每個(gè)線程都分配一個(gè)獨(dú)立的線程副本,讓多個(gè)線程只操作自己內(nèi)部的值,解決了并發(fā)訪問沖突問題,同時(shí)實(shí)現(xiàn)了線程內(nèi)的資源共享。

10、你知道ThreadLocal內(nèi)存泄露問題嗎?

線程內(nèi)都維護(hù)了ThreadLocalMap成員變量,用來存儲(chǔ)資源對(duì)象,調(diào)用set()方法,以ThreadLocal作為key,資源對(duì)象作為value,放入ThreadLocalMap集合中,然后調(diào)用get()方法到線程中查找自己key關(guān)聯(lián)的資源。然后呢,ThreadLocal有用到弱引用和強(qiáng)引用,弱引用的內(nèi)存會(huì)被回收,而強(qiáng)引用不會(huì)被回收,積累滿了就可能發(fā)生內(nèi)存泄露問題,可以使用remove()移除當(dāng)前線程資源來解決內(nèi)存泄露問題。

線程池的實(shí)現(xiàn)

配置類:

@Configuration
public class ThreadPoolExecutorConfig {
    @Bean
    public ThreadPoolExecutor threadPoolExecutor() {
        // 創(chuàng)建線程工廠
        ThreadFactory threadFactory = new ThreadFactory() {
            // 初始化線程數(shù)為1
            private int count =1;
            @Override
            public Thread newThread(@NotNull Runnable r) {
                Thread thread = new Thread(r);
                thread.setName("線程" + count);
                count++;
                return thread;
            }
        };
        return new ThreadPoolExecutor(2, 3, 1000, TimeUnit.SECONDS, new ArrayBlockingQueue<>(4), threadFactory);
    }
}

演示線程池工作流程(核心線程數(shù):2;最大線程池:3;阻塞隊(duì)列可存放任務(wù):4):

/**
 * 線程池隊(duì)列測(cè)試接口
 */
@RestController
@RequestMapping("/queue")
@Slf4j
public class QueueController {
    @Resource
    private ThreadPoolExecutor threadPoolExecutor;
// 核心線程數(shù):2;最大線程池:3;阻塞隊(duì)列可存放任務(wù):4
    @GetMapping("/add")
    public void add(String taskName){
        // 創(chuàng)建任務(wù)
        CompletableFuture.runAsync(()->{
            log.info("當(dāng)前線程:" + Thread.currentThread().getName() + "," + "正在執(zhí)行任務(wù)" + taskName);
            try {
                Thread.sleep(1000000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        },threadPoolExecutor);
    }
    @GetMapping("/get")
    public String get(){
        Map<String, Object> map = new HashMap<>();
        long taskCount = threadPoolExecutor.getTaskCount();
        map.put("任務(wù)總數(shù)", taskCount);
        long completedTaskCount = threadPoolExecutor.getCompletedTaskCount();
        map.put("已完成任務(wù)數(shù)", completedTaskCount);
        int activeCount = threadPoolExecutor.getActiveCount();
        map.put("正在執(zhí)行任務(wù)的線程數(shù)", activeCount);
        int size = threadPoolExecutor.getQueue().size();
        map.put("隊(duì)列長(zhǎng)度", size);
        return JSONUtil.toJsonStr(map);
    }
}

首先獲取到當(dāng)前狀態(tài)情況:

以此類推發(fā)送任務(wù)2后執(zhí)行情況如下:

兩個(gè)核心線程占滿,按預(yù)期接著發(fā)送任務(wù)應(yīng)該放到隊(duì)列中,隊(duì)列長(zhǎng)度+1:

因?yàn)槲覀冏枞?duì)列可以存放4個(gè)任務(wù),以此類推發(fā)滿4個(gè)隊(duì)列長(zhǎng)度后再看看效果:

發(fā)送到任務(wù)7,也就是阻塞隊(duì)列占滿4個(gè)后再發(fā)送一個(gè)任務(wù):

任務(wù)總數(shù)為7,隊(duì)列長(zhǎng)度依舊為4,可以發(fā)現(xiàn)臨時(shí)線程默認(rèn)是來執(zhí)行新來的任務(wù),而不是執(zhí)行從阻塞隊(duì)列中取出的任務(wù)來執(zhí)行。

接著再發(fā)送一個(gè)任務(wù),由于當(dāng)前線程數(shù)=最大線程數(shù),并且隊(duì)列也滿,預(yù)期應(yīng)該是走默認(rèn)拒絕策略:

符合預(yù)期。

到此這篇關(guān)于Java線程池八股及實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java線程池八股內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

衡阳县| 北流市| 洛扎县| 宣威市| 丹棱县| 贞丰县| 个旧市| 宁城县| 湘阴县| 凭祥市| 牡丹江市| 卢湾区| 大安市| 南京市| 故城县| 天台县| 陇川县| 永城市| 霍州市| 福建省| 高陵县| 吉水县| 云和县| 华亭县| 望江县| 上栗县| 昌江| 茂名市| 玛沁县| 平果县| 金塔县| 台山市| 辉南县| 手机| 化德县| 广元市| 肃宁县| 青岛市| 深泽县| 凤台县| 同德县|