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

引言

一道面試題開始~~
面試官:"假設我們有一個線程池,核心線程數爲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個任務都丟進隊列!

發散題

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

總結

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

本文卒!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章