亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java線程池使用及原理面試題

 更新時間:2022年03月11日 14:13:09   作者:Q.E.D.  
很多面試官喜歡把線程池作為問題的起點(diǎn),然后延伸到其它內(nèi)容,由于我們專欄已經(jīng)說過隊列、線程、鎖面試題了,所以本章面試題還是以線程池為主

引導(dǎo)語

線程池在日常面試中占比很大,主要是因為線程池內(nèi)容涉及的知識點(diǎn)較廣,比如涉及到隊列、線程、鎖等等,所以很多面試官喜歡把線程池作為問題的起點(diǎn),然后延伸到其它內(nèi)容,由于我們專欄已經(jīng)說過隊列、線程、鎖面試題了,所以本章面試題還是以線程池為主。

1、說說你對線程池的理解?

答:答題思路從大到小,從全面到局部,總的可以這么說,線程池結(jié)合了鎖、線程、隊列等元素,在請求量較大的環(huán)境下,可以多線程的處理請求,充分的利用了系統(tǒng)的資源,提高了處理請求的速度,細(xì)節(jié)可以從以下幾個方面闡述:

  • ThreadPoolExecutor 類結(jié)構(gòu);
  • ThreadPoolExecutor coreSize、maxSize 等重要屬性;
  • Worker 的重要作用;
  • submit 的整個過程。

通過以上總分的描述,應(yīng)該可以說清楚對線程池的理解了,如果是面對面面試的話,可以邊說邊畫出線程池的整體架構(gòu)圖(見《ThreadPoolExecutor 源碼解析》)。

2、ThreadPoolExecutor、Executor、ExecutorService、Runnable、Callable、FutureTask 之間的關(guān)系?

答:以上 6 個類可以分成兩大類:一種是定義任務(wù)類,一種是執(zhí)行任務(wù)類。

定義任務(wù)類:Runnable、Callable、FutureTask。Runnable 是定義無返回值的任務(wù),Callable 是定義有返回值的任務(wù),F(xiàn)utureTask 是對 Runnable 和 Callable 兩種任務(wù)的統(tǒng)一,并增加了對任務(wù)的管理功能;

執(zhí)行任務(wù)類:ThreadPoolExecutor、Executor、ExecutorService。Executor 定義最基本的運(yùn)行接口,ExecutorService 是對其功能的補(bǔ)充,ThreadPoolExecutor 提供真正可運(yùn)行的線程池類,三個類定義了任務(wù)的運(yùn)行機(jī)制。

日常的做法都是先根據(jù)定義任務(wù)類定義出任務(wù)來,然后丟給執(zhí)行任務(wù)類去執(zhí)行。

3、說一說隊列在線程池中起的作用?

答:作用如下:

當(dāng)請求數(shù)大于 coreSize 時,可以讓任務(wù)在隊列中排隊,讓線程池中的線程慢慢的消費(fèi)請求,實際工作中,實際線程數(shù)不可能等于請求數(shù),隊列提供了一種機(jī)制讓任務(wù)可排隊,起一個緩沖區(qū)的作用;

當(dāng)線程消費(fèi)完所有的線程后,會阻塞的從隊列中拿數(shù)據(jù),通過隊列阻塞的功能,使線程不消亡,一旦隊列中有數(shù)據(jù)產(chǎn)生后,可立馬被消費(fèi)。

4、結(jié)合請求不斷增加時,說一說線程池構(gòu)造器參數(shù)的含義和表現(xiàn)?

答:線程池構(gòu)造器各個參數(shù)的含義如下:

coreSize 核心線程數(shù);

maxSize 最大線程數(shù);

keepAliveTime 線程空閑的最大時間;

queue 有多種隊列可供選擇,比如:1:SynchronousQueue,為了避免任務(wù)被拒絕,要求線程池的 maxSize 無界,缺點(diǎn)是當(dāng)任務(wù)提交的速度超過消費(fèi)的速度時,可能出現(xiàn)無限制的線程增長;2:LinkedBlockingQueue,無界隊列,未消費(fèi)的任務(wù)可以在隊列中等待;3:ArrayBlockingQueue,有界隊列,可以防止資源被耗盡;

線程新建的 ThreadFactory 可以自定義,也可以使用默認(rèn)的 DefaultThreadFactory,DefaultThreadFactory 創(chuàng)建線程時,優(yōu)先級會被限制成 NORM_PRIORITY,默認(rèn)會被設(shè)置成非守護(hù)線程;

在 Executor 已經(jīng)關(guān)閉或?qū)ψ畲缶€程和最大隊列都使用飽和時,可以使用 RejectedExecutionHandler 類進(jìn)行異常捕捉,有如下四種處理策略:ThreadPoolExecutor.AbortPolicy、ThreadPoolExecutor.DiscardPolicy、ThreadPoolExecutor.CallerRunsPolicy、ThreadPoolExecutor.DiscardOldestPolicy。

當(dāng)請求不斷增加時,各個參數(shù)起的作用如下:

請求數(shù) < coreSize:創(chuàng)建新的線程來處理任務(wù);

coreSize <= 請求數(shù) && 能夠成功入隊列:任務(wù)進(jìn)入到隊列中等待被消費(fèi);

隊列已滿 && 請求數(shù) < maxSize:創(chuàng)建新的線程來處理任務(wù);

隊列已滿 && 請求數(shù) >= maxSize:使用 RejectedExecutionHandler 類拒絕請求。

5、coreSize 和 maxSize 可以動態(tài)設(shè)置么,有沒有規(guī)則限制?

答:一般來說,coreSize 和 maxSize 在線程池初始化時就已經(jīng)設(shè)定了,但我們也可以通過 setCorePoolSize、setMaximumPoolSize 方法動態(tài)的修改這兩個值。

setCorePoolSize 的限制見如下源碼:

// 如果新設(shè)置的值小于 coreSize,多余的線程在空閑時會被回收(不保證一定可以回收成功)
// 如果大于 coseSize,會新創(chuàng)建線程
public void setCorePoolSize(int corePoolSize) {
    if (corePoolSize < 0)
        throw new IllegalArgumentException();
    int delta = corePoolSize - this.corePoolSize;
    this.corePoolSize = corePoolSize;
    // 活動的線程大于新設(shè)置的核心線程數(shù)
    if (workerCountOf(ctl.get()) > corePoolSize)
        // 嘗試將可以獲得鎖的 worker 中斷,只會循環(huán)一次
        // 最后并不能保證活動的線程數(shù)一定小于核心線程數(shù)
        interruptIdleWorkers();
    // 設(shè)置的核心線程數(shù)大于原來的核心線程數(shù)
    else if (delta > 0) {
        // 并不清楚應(yīng)該新增多少線程,取新增核心線程數(shù)和等待隊列數(shù)據(jù)的最小值,夠用就好
        int k = Math.min(delta, workQueue.size());
        // 新增線程直到k,如果期間等待隊列空了也不會再新增
        while (k-- > 0 && addWorker(null, true)) {
            if (workQueue.isEmpty())
                break;
        }
    }
}

setMaximumPoolSize 的限制見如下源碼:

// 如果 maxSize 大于原來的值,直接設(shè)置。
// 如果 maxSize 小于原來的值,嘗試干掉一些 worker
public void setMaximumPoolSize(int maximumPoolSize) {
    if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize)
        throw new IllegalArgumentException();
    this.maximumPoolSize = maximumPoolSize;
    if (workerCountOf(ctl.get()) > maximumPoolSize)
        interruptIdleWorkers();
}

6、說一說對于線程空閑回收的理解,源碼中如何體現(xiàn)的?

答:空閑線程回收的時機(jī):如果線程超過 keepAliveTime 時間后,還從阻塞隊列中拿不到任務(wù)(這種情況我們稱為線程空閑),當(dāng)前線程就會被回收,如果 allowCoreThreadTimeOut 設(shè)置成 true,core thread 也會被回收,直到還剩下一個線程為止,如果 allowCoreThreadTimeOut 設(shè)置成 false,只會回收非 core thread 的線程。

線程在任務(wù)執(zhí)行完成之后,之所有沒有消亡,是因為阻塞的從隊列中拿任務(wù),在 keepAliveTime 時間后都沒有拿到任務(wù)的話,就會打斷阻塞,線程直接返回,線程的生命周期就結(jié)束了,JVM 會回收掉該線程對象,所以我們說的線程回收源碼體現(xiàn)就是讓線程不在隊列中阻塞,直接返回了,可以見 ThreadPoolExecutor 源碼解析章節(jié)第三小節(jié)的源碼解析。

7、如果我想在線程池任務(wù)執(zhí)行之前和之后,做一些資源清理的工作,可以么,如何做?

答:可以的,ThreadPoolExecutor 提供了一些鉤子函數(shù),我們只需要繼承 ThreadPoolExecutor 并實現(xiàn)這些鉤子函數(shù)即可。在線程池任務(wù)執(zhí)行之前實現(xiàn) beforeExecute 方法,執(zhí)行之后實現(xiàn) afterExecute 方法。

8、線程池中的線程創(chuàng)建,拒絕請求可以自定義實現(xiàn)么?如何自定義?

答:可以自定義的,線程創(chuàng)建默認(rèn)使用的是 DefaultThreadFactory,自定義話的只需要實現(xiàn) ThreadFactory 接口即可;拒絕請求也是可以自定義的,實現(xiàn) RejectedExecutionHandler 接口即可;在 ThreadPoolExecutor 初始化時,將兩個自定義類作為構(gòu)造器的入?yún)鬟f給 ThreadPoolExecutor 即可。

9、說說你對 Worker 的理解?

答:詳見《ThreadPoolExecutor 源碼解析》中 1.4 小節(jié)。

10、說一說 submit 方法執(zhí)行的過程?

答:詳見《ThreadPoolExecutor 源碼解析》中 2 小節(jié)。

11、說一說線程執(zhí)行任務(wù)之后,都在干啥?

答:線程執(zhí)行任務(wù)完成之后,有兩種結(jié)果:

線程會阻塞從隊列中拿任務(wù),沒有任務(wù)的話無限阻塞;線程會阻塞從隊列中拿任務(wù),沒有任務(wù)的話阻塞一段時間后,線程返回,被 JVM 回收。

12、keepAliveTime 設(shè)置成負(fù)數(shù)或者是 0,表示無限阻塞?

答:這種是不對的,如果 keepAliveTime 設(shè)置成負(fù)數(shù),在線程池初始化時,就會直接報 IllegalArgumentException 的異常,而設(shè)置成 0,隊列如果是 LinkedBlockingQueue 的話,執(zhí)行 workQueue.poll (keepAliveTime, TimeUnit.NANOSECONDS) 方法時,如果隊列中沒有任務(wù),會直接返回 null,導(dǎo)致線程立馬返回,不會無限阻塞。

如果想無限阻塞的話,可以把 keepAliveTime 設(shè)置的很大,把 TimeUnit 也設(shè)置的很大,接近于無限阻塞。

13、說一說 Future.get 方法是如何拿到線程的執(zhí)行結(jié)果的?

答:我們需要明確幾點(diǎn):

submit 方法的返回結(jié)果實際上是 FutureTask,我們平時都是針對接口編程,所以使用的是 Future.get 來拿到線程的執(zhí)行結(jié)果,實際上是 FutureTask.get ,其方法底層是從 FutureTask 的 outcome 屬性拿值的;《ThreadPoolExecutor 源碼解析》中 2 小節(jié)中詳細(xì)說明了 submit 方法最終會把線程的執(zhí)行結(jié)果賦值給 outcome。

結(jié)合 1、2,當(dāng)線程執(zhí)行完成之后,自然就可以從 FutureTask 的 outcome 屬性中拿到值。

14、總結(jié)

如果我們弄清楚 ThreadPoolExecutor 的原理之后,線程池的面試題都很簡單,所以建議大家多看看 《ThreadPoolExecutor 源碼解析》這小節(jié)。

以上就是java線程池使用及原理面試題的詳細(xì)內(nèi)容,更多關(guān)于java線程池面試題的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論