<cite id="ffb66"></cite><cite id="ffb66"><track id="ffb66"></track></cite>
      <legend id="ffb66"><li id="ffb66"></li></legend>
      色婷婷久,激情色播,久久久无码专区,亚洲中文字幕av,国产成人A片,av无码免费,精品久久国产,99视频精品3
      網易首頁 > 網易號 > 正文 申請入駐

      面試官一個線程池問題把我問懵逼了

      0
      分享至

      原創 why技術

      前幾天,有個朋友在微信上找我。他問:why哥,在嗎?

      我說:發生腎么事了?

      他啪的一下就提了一個問題啊,很快。

      我大意了,隨意瞅了一眼,這題不是很簡單嗎?

      結果沒想到里面還隱藏著一篇文章。

      故事,得從這個問題說起:


      上面的圖中的線程池配置是這樣的:

      ExecutorService executorService = new ThreadPoolExecutor(40, 80, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(100), new DefaultThreadFactory("test"), new ThreadPoolExecutor.DiscardPolicy());

      上面這個線程池里面的參數、執行流程啥的我就不再解釋了。

      畢竟我曾經在《一人血書,想讓why哥講一下這道面試題。》這篇文章里面發過毒誓的,再說就是小王吧了:


      上面的這個問題其實就是一個非常簡單的八股文問題:

      非核心線程在什么時候被回收?

      如果經過 keepAliveTime 時間后,超過核心線程數的線程還沒有接受到新的任務,就會被回收。

      標準答案,完全沒毛病。

      那么我現在帶入一個簡單的場景,為了簡單直觀,我們把線程池相關的參數調整一下:

      ExecutorService executorService = new ThreadPoolExecutor(2, 3, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<>(2), new DefaultThreadFactory("test"), new ThreadPoolExecutor.DiscardPolicy());

      那么問題來了:

      這個線程最多能容納的任務是不是 5 個?
      假設任務需要執行 1 秒鐘,那么我直接循環里面提交 5 個任務到線程池,肯定是在 1 秒鐘之內提交完成,那么當前線程池的活躍線程是不是就是 3 個?
      如果接下來的 30 秒,沒有任務提交過來。那么 30 秒之后,當前線程池的活躍線程是不是就是 2 個?

      上面這三個問題的答案都是肯定的,如果你搞不明白為什么,那么我建議你先趕緊去補充一下線程池相關的知識點,下面的內容你強行看下去肯定是一臉懵逼的。

      接下來的問題是這樣的:

      如果當前線程池的活躍線程是 3 個(2 個核心線程+ 1 個非核心線程),但是它們各自的任務都執行完成了,都處于 waiting 狀態。然后我每隔 3 秒往線程池里面扔一個耗時 1 秒的任務。那么 30 秒之后,活躍線程數是多少?

      先說答案:還是 3 個。

      從我個人正常的思維,是這樣的:核心線程是空閑的,每隔 3 秒扔一個耗時 1 秒的任務過來,所以僅需要一個核心線程就完全處理的過來。

      那么,30 秒內,超過核心線程的那一個線程一直處于等待狀態,所以 30 秒之后,就被回收了。 但是上面僅僅是我的主觀認為,而實際情況呢?

      30 秒之后,超過核心線程
      的線程并不會被回收,活躍線程還是 3 個。 到這里,如果你知道是 3 個,且知道為什么是 3 個,即了解為什么非核心線程并沒有被回收,那么接下里的內容應該就是你已經掌握的了。

      可以不看,拉到最后,點個贊,去忙自己的事情吧。

      如果你不知道,可以接著看,了解一下為什么是 3 個。

      雖然我相信沒有面試官會問這樣的問題,但是對于你去理解線程池,是有幫助的。

      先上 Demo

      基于我前面說的這個場景,碼出代碼如下:

      public class ThreadTest { @Test public void test() throws InterruptedException { ThreadPoolExecutor executorService = new ThreadPoolExecutor(2, 3, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<>(2), new DefaultThreadFactory("test"), new ThreadPoolExecutor.DiscardPolicy()); //每隔兩秒打印線程池的信息 ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); scheduledExecutorService.scheduleAtFixedRate(() -> { System.out.println("=====================================thread-pool-info:" + new Date() + "====================================="); System.out.println("CorePoolSize:" + executorService.getCorePoolSize()); System.out.println("PoolSize:" + executorService.getPoolSize()); System.out.println("ActiveCount:" + executorService.getActiveCount()); System.out.println("KeepAliveTime:" + executorService.getKeepAliveTime(TimeUnit.SECONDS)); System.out.println("QueueSize:" + executorService.getQueue().size()); }, 0, 2, TimeUnit.SECONDS); try { //同時提交5個任務,模擬達到最大線程數 for (int i = 0; i < 5; i++) { executorService.execute(new Task()); } } catch (Exception e) { e.printStackTrace(); } //休眠10秒,打印日志,觀察線程池狀態 Thread.sleep(10000); //每隔3秒提交一個任務 while (true) { Thread.sleep(3000); executorService.submit(new Task()); } } static class Task implements Runnable { @Override public void run(){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread() + "-執行任務"); } }}

      這份代碼也是提問的哥們給我的,我做了微調,你直接粘出去就能跑起來。

      show me code,no bb。這才是相互探討的正確姿勢。

      這個程序的運行結果是這樣的:


      一共五個任務,線程池的運行情況是什么樣的呢?

      先看標號為 ① 的地方:

      三個線程都在執行任務,然后 2 號線程和 1 號線程率先完成了任務,接著把隊列里面的兩個任務拿出來執行(標號為 ② 的地方)。

      按照程序,接下來,每隔 3 秒就有一個耗時 1 秒的任務過來。而此時線程池里面的三個活躍線程都是空閑狀態。

      那么問題就來了:

      該選擇哪個線程來執行這個任務呢?是隨機選一個嗎?

      雖然接下來的程序還沒有執行,但是基于前面的截圖,我現在就可以告訴你,接下來的任務,線程執行順序為:

      Thread[test-1-3,5,main]-執行任務
      Thread[test-1-2,5,main]-執行任務
      Thread[test-1-1,5,main]-執行任務
      Thread[test-1-3,5,main]-執行任務
      Thread[test-1-2,5,main]-執行任務
      Thread[test-1-1,5,main]-執行任務
      ......

      即雖然線程都是空閑的,但是當任務來的時候不是隨機調用的,而是輪詢。

      由于是輪詢,每三秒執行一次,所以非核心線程的空閑時間最多也就是 9 秒,不會超過 30 秒,所以一直不會被回收。

      基于這個 Demo,我們就從表象上回答了,為什么活躍線程數一直為 3。

      為什么是輪詢?

      我們通過 Demo 驗證了上面場景中,線程執行順序為輪詢。

      那么為什么呢?

      這只是通過日志得出的表象呀,內部原理呢?對應的代碼呢?

      這一小節帶大家看一下到底是怎么回事。

      首先我看到這個表象的時候我就猜測:這三個線程肯定是在某個地方被某個隊列存起來了,基于此,才能實現輪詢調用。

      所以,我一直在找這個隊列,一直沒有找到對應的代碼,我還有點著急了。想著不會是在操作系統層面控制的吧?

      后來我冷靜下來,覺得不太可能。于是電光火石之間,我想到了,要不先 Dump 一下線程,看看它們都在干啥:


      Dump 之后,這玩意我眼熟啊,AQS 的等待隊列啊。

      根據堆棧信息,我們可以定位到這里的源碼:

      java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#awaitNanos


      看到這里的時候,我才一下恍然大悟了起來。

      害,是自己想的太多了。

      說穿了,這其實就是個生產者-消費者的問題啊。

      三個線程就是三個消費者,現在沒有任務需要處理,它們就等著生產者生產任務,然后通知它們準備消費。

      由于本文只是帶著你去找答案在源碼的什么地方,不對源碼進行解讀。

      所以我默認你是對 AQS 是有一定的了解的。

      可以看到 addConditionWaiter 方法其實就是在操作我們要找的那個隊列。學名叫做等待隊列。

      Debug 一下,看看隊列里面的情況:


      巧了嘛,這不是。順序剛好是:

      Thread[test-1-3,5,main]
      Thread[test-1-2,5,main]
      Thread[test-1-1,5,main]

      消費者這邊我們大概摸清楚了,接著去看看生產者。

      java.util.concurrent.ThreadPoolExecutor#execute


      線程池是在這里把任務放到隊列里面去的。

      而這個方法里面的源碼是這樣的:


      其中signalNotEmpty() 最終會走到 doSignal 方法,而該方法里面會調用 transferForSignal 方法。

      這個方法里面會調用 LockSupport.unpark(node.thred) 方法,喚醒線程:


      而喚醒的順序,就是等待隊列里面的順序:


      所以,現在你知道當一個任務來了之后,這個任務該由線程池里面的哪個線程執行,這個不是隨機的,也不是隨便來的。

      是講究一個順序的。

      什么順序呢?

      Condition 里面的等待隊列里面的順序。

      什么,你不太懂 Condition?

      那還不趕緊去學?等著我給你講呢?

      本來我是想寫一下的,后來發現《Java并發編程的藝術》一書中的 5.6.2 小節已經寫的挺清楚了,圖文并茂。這部分內容其實也是面試的時候的高頻考點,所以自己去看看就好了。


      先欠著,欠著。


      非核心線程怎么回收?

      還是上面的例子,假設非核心線程就空閑了超過 30 秒,那么它是怎么被回收的呢?

      這個也是一個比較熱門的面試題。

      這題沒有什么高深的地方,答案就藏在源碼的這個地方:

      java.util.concurrent.ThreadPoolExecutor#getTask


      當 timed 參數為 true 的時候,會執行 workQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS) 方法。

      而 timed 什么時候為 true 呢?

      boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

      allowCoreThreadTimeOut 默認為 false。


      所以,就是看 wc > corePoolSize 條件,wc 是活躍線程數。此時活躍線程數為 3 ,大于核心線程數 2。

      因此 timed 為 true。

      也就是說,當前 workQueue 為空的時候,現在三個線程都阻塞 workQueue.poll 方法中。

      而當指定時間后,workQueue 還是為空,則返回為 null。

      于是在 1077 行把 timeOut 修改為 true。

      進入一下次循環,返回 null。

      最終會執行到這個方法:

      java.util.concurrent.ThreadPoolExecutor#processWorkerExit


      而這個方法里面會執行 remove 的操作。

      于是線程就被回收了。

      所以當超過指定時間后,線程會被回收。

      那么被回收的這個線程是核心線程還是非核心線程呢?

      不知道。

      因為在線程池里面,核心線程和非核心線程僅僅是一個概念而已,其實拿著一個線程,我們并不能知道它是核心線程還是非核心線程。

      這個地方就是一個證明,因為當工作線程多余核心線程數之后,所有的線程都在 poll,也就是說所有的線程都有可能被回收:


      另外一個強有力的證明就是 addWorker 這里:


      core 參數僅僅是控制取 corePoolSize 還是 maximumPoolSize。

      所以,這個問題你說怎么回答:


      JDK 區分的方式就是不區分。

      那么我們可以知道嗎?

      可以,比如通過觀察日志,前面的案例中,我就知道這兩個是核心線程,因為它們最先創建:

      Thread[test-1-1,5,main]-執行任務
      Thread[test-1-2,5,main]-執行任務

      在程序里面怎么知道呢?

      目前是不知道的,但是這個需求,加錢就可以實現。


      自己擴展一下線程池嘛,給線程池里面的線程打個標還不是一件很簡單的事情嗎?

      只是你想想,你區分這玩意干啥,有沒有可落地的需求?

      畢竟,脫離需求談實現。都是耍流氓。

      最后說一句

      才疏學淺,難免會有紕漏,如果你發現了錯誤的地方,可以在后臺提出來,我對其加以修改。

      特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。

      Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

      相關推薦
      熱點推薦
      北京公交專用道行駛時間,又有新調整!

      北京公交專用道行駛時間,又有新調整!

      BRTV新聞
      2026-04-28 12:40:41
      我在中東教漢語,娶了三個本地女孩,雖然年入百萬,卻并不幸福

      我在中東教漢語,娶了三個本地女孩,雖然年入百萬,卻并不幸福

      千秋文化
      2026-04-20 19:55:30
      三分球23投0中!廣東祭出最強死亡五鐵:杜鋒恐被他們打下課?

      三分球23投0中!廣東祭出最強死亡五鐵:杜鋒恐被他們打下課?

      籃球快餐車
      2026-04-29 03:01:53
      有人說:打麻將和性生活是縣城的底色?

      有人說:打麻將和性生活是縣城的底色?

      燈錦年
      2026-04-21 12:32:46
      尤伯杯:國羽3連勝!王祉怡力克世錦賽冠軍,陳雨菲橫掃世界第39

      尤伯杯:國羽3連勝!王祉怡力克世錦賽冠軍,陳雨菲橫掃世界第39

      釘釘陌上花開
      2026-04-28 06:54:31
      公開反歧視,TA:至少一位俱樂部主席聯系了孔帕尼,表達欽佩

      公開反歧視,TA:至少一位俱樂部主席聯系了孔帕尼,表達欽佩

      懂球帝
      2026-04-29 04:34:07
      哭窮了!一線男1號片酬跌至巔峰期3折,網友:待遇比醫生差才合理

      哭窮了!一線男1號片酬跌至巔峰期3折,網友:待遇比醫生差才合理

      火山詩話
      2026-04-28 07:27:33
      苑瓊丹遭東北親戚“道德綁架”!97歲姑奶隔空喊話,態度早就表明

      苑瓊丹遭東北親戚“道德綁架”!97歲姑奶隔空喊話,態度早就表明

      裕豐娛間說
      2026-04-27 22:41:52
      燃氣公司上門安檢,根本不是查漏氣!真正目的其實是這3個

      燃氣公司上門安檢,根本不是查漏氣!真正目的其實是這3個

      匹夫來搞笑
      2026-04-20 13:24:51
      “望月鱔劇毒,誤食必死”,望月鱔比毒蛇還要毒?什么是望月鱔?你們有遇到過嗎?

      “望月鱔劇毒,誤食必死”,望月鱔比毒蛇還要毒?什么是望月鱔?你們有遇到過嗎?

      農夫也瘋狂
      2026-04-26 11:01:20
      雨水連綿氣溫跳水!江蘇先冷后暖,五一當天直沖26℃

      雨水連綿氣溫跳水!江蘇先冷后暖,五一當天直沖26℃

      現代快報
      2026-04-28 22:19:32
      “盡快撤離”!廣州緊急提醒:今晚雨更大

      “盡快撤離”!廣州緊急提醒:今晚雨更大

      南方都市報
      2026-04-28 18:24:45
      經常睡覺的房間,盡量別放這3樣東西!并非迷信,轉告家人

      經常睡覺的房間,盡量別放這3樣東西!并非迷信,轉告家人

      芹姐說生活
      2026-04-26 16:29:18
      公安部回應,紅綠燈7月1日起全國取消?不要再被帶偏了!

      公安部回應,紅綠燈7月1日起全國取消?不要再被帶偏了!

      牛鍋巴小釩
      2026-04-28 11:36:03
      英足總和英超聯賽應感到尷尬——他們讓瓜迪奧拉別無選擇

      英足總和英超聯賽應感到尷尬——他們讓瓜迪奧拉別無選擇

      綠茵情報局
      2026-04-29 01:51:06
      李想稱理想L9 Livis比上汽大眾ID.ERA 9X至少領先兩代,大眾高管回應:理想僅價格和營銷水平領先,我們絕不會自稱是“500萬內最好”產品

      李想稱理想L9 Livis比上汽大眾ID.ERA 9X至少領先兩代,大眾高管回應:理想僅價格和營銷水平領先,我們絕不會自稱是“500萬內最好”產品

      魯中晨報
      2026-04-27 11:28:06
      A股:2.5億股民,今晚可能要興奮得睡不著覺了,你知道為什么嗎?

      A股:2.5億股民,今晚可能要興奮得睡不著覺了,你知道為什么嗎?

      夜深愛雜談
      2026-04-28 21:44:29
      我入住養老院6年,勸告想來養老的老人,要先看自己能否做到這4點

      我入住養老院6年,勸告想來養老的老人,要先看自己能否做到這4點

      小馬達情感故事
      2026-04-26 18:50:03
      打起來了,以軍不宣而戰;內塔尼亞胡迎來勁敵,或被關進大牢!

      打起來了,以軍不宣而戰;內塔尼亞胡迎來勁敵,或被關進大牢!

      說歷史的老牢
      2026-04-27 23:23:31
      女子花4080元,溢價買男團演唱會門票,想退退不了,票還被他人用了!二手平臺稱處理無誤,上海警方出手了!

      女子花4080元,溢價買男團演唱會門票,想退退不了,票還被他人用了!二手平臺稱處理無誤,上海警方出手了!

      大風新聞
      2026-04-28 19:46:03
      2026-04-29 05:03:00
      軟測試驗田
      軟測試驗田
      軟件測試領域最新最前沿資訊
      117文章數 128關注度
      往期回顧 全部

      科技要聞

      10億周活目標落空!傳OpenAI爆發內部分歧

      頭條要聞

      19歲中國女孩被困緬甸 交20萬贖金園區仍未放人

      頭條要聞

      19歲中國女孩被困緬甸 交20萬贖金園區仍未放人

      體育要聞

      魔術黑八活塞,一步之遙?!

      娛樂要聞

      蔡卓妍官宣結婚,老公比她小10歲

      財經要聞

      中央政治局會議定調,八大看點速覽!

      汽車要聞

      拒絕瘋狂套娃!現代艾尼氪金星長在未來審美點上

      態度原創

      教育
      游戲
      親子
      公開課
      軍事航空

      教育要聞

      教育部通知,今年9月份開始,上學的規則全變了

      這不爽翻了?曝PS6或能穩穩運行60幀+光追的游戲畫面

      親子要聞

      拍這期視頻時眼淚止不住地流

      公開課

      李玫瑾:為什么性格比能力更重要?

      軍事要聞

      德國總理默茨:美國正遭受伊朗領導層的羞辱

      無障礙瀏覽 進入關懷版 主站蜘蛛池模板: 国产精品无码素人福利不卡| 欧美日韩欧美| 狠狠躁天天躁中文字幕| 人妻无码中文久久久久专区| 四虎永久精品免费视频| 任你艹| 亚洲AV无码国产永久播放蜜芽| 国产人妻熟女呻吟在线观看| 久久人人爽人人爽人人片av高清| 免费无码毛片一区二区app| 精品视频福利| 国产浮力第一页| 欧美日韩亚洲综合在线观看| 亚洲欧美日韩国产美色| 亚洲日韩一区二区| 亚洲日韩精品欧美一区二区一| 亚洲精品日韩在线观看| 亚洲欧洲av| 少妇大胆瓣开下部自慰| 国产精品成人国产乱| 97人人模人人爽人人喊电影 | 超碰老司机| 鄂伦春自治旗| 97久久久亚洲综合久久| 日韩人妻精品无码制服| 中国大陆高清aⅴ毛片| 最新午夜男女福利片视频| 拳交AV| 99视频精品全部在线观看| 网站av| 麻豆精品一区综合av在线| 国产午夜成人久久无码一区二区| 亚洲最大成人网站| 人妻无码中文专区久久app | 少妇伦子伦精品无吗| 99久久久无码国产精品免费| 亚洲色大成网站www永久| 国产精品自在自线免费观看| 亚洲一区在线成人av| 99国产成人综合久久精品| 国产精品视频一区二区三区不卡 |