java面試——線程池

相關問題

1揪利、工作流程是怎么樣的植锉。
2泥栖、核心參數(shù)礼烈。
3弧满、任務結(jié)束之后如何恢復到核心線程數(shù)。
4此熬、線程池運行時有一個線程報錯了會怎么樣谱秽。
5、如何合理設置核心線程數(shù)的大小
6摹迷、不同子線程之間怎么傳遞數(shù)據(jù)
7、5個核心線程數(shù)郊供,30個任務隊列峡碉,20個最大線程數(shù),200s存活時間驮审,一個for循環(huán)加入20個任務鲫寄,
這個時候線程池中有多少個。

1疯淫、工作流程是怎么樣的地来。

execute方法

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * Proceed in 3 steps:
         * 1.如果運行的線程少于核心線程數(shù),嘗試新建一個線程作為第一個任務熙掺。
         *
         * 2. 如果有任務可以成功排隊未斑,那就加入隊列
         *
         * 3. 如果無法加入隊列,那么嘗試添加一個新線程币绩。
         * 要是失敗了就知道被關閉或包和了蜡秽,因此拒絕這項任務
         */
        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))
            reject(command);
    }

image.png

2、核心參數(shù)缆镣。如何合理設置核心線程數(shù)的大小

  1. 最?線程數(shù)maximumPoolSize

  2. 核?線程數(shù)corePoolSize

    任務隊列的長度要根據(jù)核心線程數(shù)芽突,以及系統(tǒng)對任務響應時間的要求有關。隊列長度可以設置為 所有核心線程每秒處理任務數(shù) * 每個任務響應時間 = 每秒任務總響應時間 董瞻,即(corePoolSizethreadtasks)responsetime: (2010)2=400寞蚌,即隊列長度可設置為400。

  3. 活躍時間keepAliveTime

    當負載降低時钠糊,可減少線程數(shù)量挟秤,當線程的空閑時間超過keepAliveTime,會自動釋放線程資源眠蚂。默認情況下線程池停止多余的線程并最少會保持corePoolSize個線程煞聪。

  4. 阻塞隊列workQueue

    BlockingQueue workQueue = null; workQueue = new ArrayBlockingQueue<>(5);//基于數(shù)組的先進先出隊列,有界 workQueue = new LinkedBlockingQueue<>();//基于鏈表的先進先出隊列逝慧,無界 workQueue = new SynchronousQueue<>();//無緩沖的等待隊列昔脯,無界

  5. 拒絕策略RejectedExecutionHandler

可繼承后進行自定義啄糙。

提供的拒絕策略有:

  1. AbortPolicy:直接丟棄任務,拋出異常云稚,這是默認策略
  2. CallerRunsPolicy:只?調(diào)?者所在的線程來處理任務
  3. DiscardOldestPolicy:丟棄等待隊列中最舊的任務隧饼,并執(zhí)?當前任務
  4. DiscardPolicy:直接丟棄任務,也不拋出異常
  5. allowCoreThreadTimeout

默認情況下核心線程不會退出静陈,可通過將該參數(shù)設置為true燕雁,讓核心線程也退出。

一般說來鲸拥,大家認為線程池的大小經(jīng)驗值應該這樣設置:(其中N為CPU的個數(shù))

  • 如果是CPU密集型應用拐格,則線程池大小設置為N+1
  • 如果是IO密集型應用,則線程池大小設置為2N+1

3刑赶、任務結(jié)束之后如何恢復到核心線程數(shù)/線程池中多余的線程是如何回收的捏浊?

什么時候回收線程?

ThreadPoolExecutor回收工作線程撞叨,一條線程getTask()返回null金踪,就會被回收。

分為兩種情況

一牵敷、未調(diào)用shutdown() 胡岔,RUNNING狀態(tài)下全部任務執(zhí)行完成的場景

線程數(shù)量大于corePoolSize,線程超時阻塞枷餐,超時喚醒后CAS減少工作線程數(shù)靶瘸,如果CAS成功,返回null尖淘,線程回收奕锌。否則進入下一次循環(huán)。當工作者線程數(shù)量小于等于corePoolSize村生,就可以一直阻塞了惊暴。

二、調(diào)用shutdown() 趁桃,全部任務執(zhí)行完成的場景

2.1 所有線程都在阻塞

中斷喚醒辽话,進入循環(huán),都符合第一個if判斷條件卫病,都返回null油啤,所有線程回收。

2.2 任務還沒有完全執(zhí)行完

至少會有一條線程被回收蟀苛。在processWorkerExit(Worker w, boolean completedAbruptly)方法里會調(diào)用tryTerminate()益咬,向任意空閑線程發(fā)出中斷信號。所有被阻塞的線程帜平,最終都會被一個個喚醒幽告,回收梅鹦。

如何被回收的。

private void processWorkerExit(Worker w, boolean completedAbruptly) {
        if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
            decrementWorkerCount();

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            completedTaskCount += w.completedTasks;
//這里就是回收線程的主要操作了冗锁,移除線程池對該線程的引用齐唆,使其可以被JVM正常地回收
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }

        tryTerminate();

        int c = ctl.get();
        if (runStateLessThan(c, STOP)) {
            if (!completedAbruptly) {
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;
                if (workerCountOf(c) >= min)
                    return; // replacement not needed
            }
            addWorker(null, false);
        }
    }

runWorker()方法中被執(zhí)行

image.png

ThreadPoolExecutor是怎么回收線程的:

https://juejin.cn/post/6922069411981426702

4、線程池運行時有一個線程報錯了會怎么樣冻河。

當一個線程池里面的線程異常后:

1箍邮、當執(zhí)行方式是execute時,可以看到堆棧異常的輸出

ThreadPoolExecutor.runWorker()方法中,task.run()叨叙,即執(zhí)行我們的方法锭弊,如果異常的話會throw x;所以可以看到異常。

2擂错、當執(zhí)行方式是submit時,堆棧異常沒有輸出廷蓉。但是調(diào)用Future.get()方法時,可以捕獲到異常

ThreadPoolExecutor.runWorker()方法中马昙,task.run(),其實還會繼續(xù)執(zhí)行FutureTask.run()方法刹悴,再在此方法中c.call()調(diào)用我們的方法行楞,如果報錯是setException(),并沒有拋出異常土匀。當我們?nèi)et()時子房,會將異常拋出。

3就轧、不會影響線程池里面其他線程的正常執(zhí)行

4证杭、線程池會把這個線程移除掉,并創(chuàng)建一個新的線程放到線程池中

當線程異常妒御,會調(diào)用ThreadPoolExecutor.runWorker()方法最后面的finally中的processWorkerExit()解愤,會將此線程remove,并重新addworker()一個線程乎莉。

execute的入?yún)⑹荝unnable送讲, 沒有返回值。任務通過execute提交后就基本和主線程脫離關系了惋啃。

submit的入?yún)⒖梢允荂allable(也可以是Runnable)哼鬓,并且有返回值,返回的是一個Future對象边灭,然后通過對象的get方法獲取任務執(zhí)行的結(jié)果异希。

5、不同子線程之間怎么傳遞數(shù)據(jù)

6绒瘦、5個核心線程數(shù)称簿,30個任務隊列扣癣,20個最大線程數(shù),200s存活時間予跌,一個for循環(huán)加入20個任務搏色,這個時候線程池中有多少個。

結(jié)合線程池的工作原理就能知道有5個活躍線程

代碼.png
運行結(jié)果.png
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末券册,一起剝皮案震驚了整個濱河市频轿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌烁焙,老刑警劉巖航邢,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異骄蝇,居然都是意外死亡膳殷,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門九火,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赚窃,“玉大人,你說我怎么就攤上這事岔激±占” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵虑鼎,是天一觀的道長辱匿。 經(jīng)常有香客問我,道長炫彩,這世上最難降的妖魔是什么匾七? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮江兢,結(jié)果婚禮上昨忆,老公的妹妹穿的比我還像新娘。我一直安慰自己杉允,他們只是感情好扔嵌,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著夺颤,像睡著了一般痢缎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上世澜,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天独旷,我揣著相機與錄音,去河邊找鬼。 笑死嵌洼,一個胖子當著我的面吹牛案疲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播麻养,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼褐啡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了鳖昌?” 一聲冷哼從身側(cè)響起备畦,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎许昨,沒想到半個月后懂盐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡糕档,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年莉恼,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片速那。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡俐银,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出端仰,到底是詐尸還是另有隱情悉患,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布榆俺,位于F島的核電站,受9級特大地震影響坞淮,放射性物質(zhì)發(fā)生泄漏茴晋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一回窘、第九天 我趴在偏房一處隱蔽的房頂上張望诺擅。 院中可真熱鬧,春花似錦啡直、人聲如沸烁涌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽撮执。三九已至,卻和暖如春舷丹,著一層夾襖步出監(jiān)牢的瞬間抒钱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谋币,地道東北人仗扬。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像蕾额,于是被迫代替她去往敵國和親早芭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容