面試官:這道線程池場景題回答一下?

引言

一道面試題開始~~面試官:"假設我們有一個線程池,核心線程數為10,最大線程數也為20,任務隊列為100。現在來了100個任務,線程池裡現在有幾個線程運行?"粉絲豪:"應該是10吧。"面試官:"你確定?"粉絲豪:"確定啊,就是10…"於是乎,粉絲豪就回去等通知了~

此題的陷阱,大家如果看出來了,本文就不用看了!其實這道題正確的答案是"不一定!"因為並沒指明是哪一種線程池機制,帶著我們的疑問繼續往下看!

ps:不要糾結這題是不是咬文嚼字,現在人多如米,題目就是這樣坑~

正文

先進隊列,到最大值,再起線程

這種情況是大家最容易想到的情況,因為JDK中的線程池,也就是ThreadPoolExecutor就是這種機制的!

OK,我們先來看一下ThreadPoolExecutor的execute方法,如下圖所示

面試官:這道線程池場景題回答一下?


看到三個紅框了吧(其實源碼裡有解釋),對應的三步分別是

  • (1)判斷當前活躍線程數是否小於corePoolSize,如果小於,則調用addWorker創建線程執行任務
  • (2)如果不小於corePoolSize,則將任務添加到workQueue隊列
  • (3)如果放入workQueue失敗,則創建線程執行任務,如果這時創建線程失敗(當前線程數不小於maximumPoolSize時),就會調用reject(內部調用handler)拒絕接受任務。

用一張圖來解釋如下

面試官:這道線程池場景題回答一下?

如圖所示,默認的機制為線程池裡的核心線程數不夠了,後面進來的任務會先丟隊列,當隊列滿了,才起新線程。

因此,按照這套機制!粉絲豪的回答是正確的,當有100個任務添加進來時,剩下先起10個核心線程,剩下90個任務都丟進隊列裡,因此線程池裡只有10個線程在執行!

但是,有一種線程池機制的是這樣的

先起線程,到最大值,再進隊列

不知道大家有沒聽過在dubbo中,有一種線程池叫EagerThreadPoolExecutor線程池。該線程池的execute方法如下所示

面試官:這道線程池場景題回答一下?


它調的還是父類的execute方法,也還是ThreadPoolExecutor中的execute方法!
但是,它的隊列!是一種自定義隊列,叫TaskQueue,它的offer方法如下

面試官:這道線程池場景題回答一下?

這個offer方法的最核心的是紅框中那步,當前線程數小於最大線程數時,則直接返回false。

ThreadPoolExecutor中的execute方法中的第二步的條件中,如果workQueue.offer返回為fasle,則直接進入第三步,創建新任務!如下圖所示

面試官:這道線程池場景題回答一下?

EagerThreadPoolExecutor線程池通過自定義隊列的這麼一種形式,改寫了線程池的機制。這種線程池的機制是核心線程數不夠了,先起線程,當線程達到最大值後,後面的任務就丟進隊列!

因此,如果按照這麼一套機制,粉絲豪的答案就不正確了。當100個任務添加進來時,直接會起20個線程,剩下80個任務都丟進隊列!

發散題

這是一道真實的發散題,其實問法也是差不多的。如果上面的內容能看懂,這道題也能答的上來!

面試官:這道線程池場景題回答一下?

總結

小小的線程池,大大的坑~希望大家有所收穫~~

本文卒!


分享到:


相關文章: