<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試被問(wèn)線程池,真香

          共 4277字,需瀏覽 9分鐘

           ·

          2021-04-25 09:35

          面試官 :   看你簡(jiǎn)歷上寫(xiě)了對(duì)系統(tǒng)性能做了優(yōu)化,能簡(jiǎn)單給我介紹一下嗎?都有哪些優(yōu)化,你是怎么衡量?jī)?yōu)化效果的?

          :  巴拉巴拉。。。例如我們系統(tǒng)之前要查詢(xún)用戶(hù)的個(gè)人身份信息、聯(lián)系人信息、訂單狀態(tài)信息、積分信息,之前系統(tǒng)是單線程串行處理的,我用線程池對(duì)四個(gè)任務(wù)并行處理,然后對(duì)處理結(jié)果合并。

          面試官 :   你剛才說(shuō)用到線程池,能跟我講講為什么用線程池嗎?我創(chuàng)建四個(gè)線程處理可不可以?

          :   可以,當(dāng)然可以。

          擺手

          :   但是用線程池更合適。阿里巴巴開(kāi)發(fā)規(guī)約中有一條:

          3.【強(qiáng)制】線程資源必須通過(guò)線程池提供,不允許在應(yīng)用中自行顯式創(chuàng)建線程。
          說(shuō)明:使用線程池的好處是減少在創(chuàng)建和銷(xiāo)毀線程上所消耗的時(shí)間以及系統(tǒng)資源的開(kāi)銷(xiāo),解決資源不足的問(wèn)題。如果不使用線程池,有可能造成系統(tǒng)創(chuàng)建大量同類(lèi)線程而導(dǎo)致消耗完內(nèi)存或者“過(guò)度切換”的問(wèn)題。
          《阿里巴巴研發(fā)手冊(cè)》

          :  就像你去餐廳吃飯,服務(wù)員總是提前洗好盤(pán)子,不會(huì)等你來(lái)打飯的時(shí)候才洗盤(pán)子,盤(pán)子就像是線程池里的線程,你打飯就是要處理的任務(wù)。

          面試官 :  那你知道線程池的相關(guān)類(lèi)關(guān)系嗎?

          :   這算什么問(wèn)題?不應(yīng)該是問(wèn)我核心線程數(shù)怎么設(shè)置嗎?好吧。。。請(qǐng)看下圖:

          • Executor 的定義非常簡(jiǎn)單,就定義了線程池最本質(zhì)要做的事,執(zhí)行任務(wù)。

          public interface Executor {

              void execute(Runnable command);
          }

          • ExecutorService 也是個(gè)接口,不過(guò)他算是把線程池的框架搭出來(lái)了,告訴要實(shí)現(xiàn)它的線程池必須提供的一些管理線程池的方法。
          • AbstractExecutorService 是普通的線程池執(zhí)行器,ScheduledExecutorService 是定時(shí)任務(wù)線程池。
          面試官 :  那你日常開(kāi)發(fā)中是怎么創(chuàng)建線程池的?
          :  我用ThreadPoolExecutor 自定義創(chuàng)建線程池。
          面試官 :  那你知道線程池都有哪些核心參數(shù)嗎?
          :  線程池主要的核心參數(shù)有7個(gè),我們看 ThreadPoolExecutor  構(gòu)造函數(shù)就知道了
          1. corePoolSize :核心線程數(shù)
          2. maximumPoolSize: 最大線程數(shù)
          3. keepAliveTime :線程在線程池中不被銷(xiāo)毀的空閑時(shí)間,如果線程池的線程太多,任務(wù)比較小,到這個(gè)時(shí)間就銷(xiāo)毀線程池。
            unit : keepAliveTime 的時(shí)間單位,一般設(shè)置成秒或毫秒。
          4. workQueue : 任務(wù)隊(duì)列,存放等待執(zhí)行的任務(wù)
          5. threadFactory: 創(chuàng)建線程的任務(wù)工廠,比如給線程命名加上前綴,后面會(huì)講
          6. handler : 拒絕任務(wù)處理器,當(dāng)任務(wù)處理不過(guò)來(lái)時(shí)的拒絕處理器
          7. allowCoreThreadTimeOut : 是否允許核心線程超時(shí)銷(xiāo)毀,這個(gè)參數(shù)不在構(gòu)造函數(shù)中,但重要性也很高
          面試官 : 老實(shí)說(shuō),你是不是來(lái)之前背過(guò)了,不然怎么可能都記住了。
          :   [掀桌子],不面了,還找什么工作,要什么自行車(chē)。
          面試官 :  其實(shí)剛才那也是問(wèn)題,考察面試者是否皮實(shí),我們繼續(xù)。
          面試官 :  剛才說(shuō)了這些核心參數(shù),你能不能跟我講講線程池的基本工作原理。
          : 可以的,這里我給你畫(huà)個(gè)流程,如下所示:
          面試官 :  那按照上面的流程寫(xiě)段偽代碼。
          :  還能不能好好面了,讓手撕線程池。
          那好吧,你對(duì)著????的流程圖看,代碼如下:
          面試官 :  不錯(cuò),那你平常怎么管理線程池的呢?
          :  我會(huì)搞了個(gè)線程池管理器,比如 ThreadPoolManager,有個(gè)私有變量的Map,按照線程池的作用給他取個(gè)名字,比如起名為: preparePlateThreadPool (準(zhǔn)備餐盤(pán)線程池),把線程池名稱(chēng)定義成常量,和創(chuàng)建好的線程池放到管理器的Map里。
          面試官 :  除了你自己用 ThreadPoolExecutor 創(chuàng)建線程池,還有別的方式嗎?
          :  java.util.concurrent 包里提供的 Executors 也可以用來(lái)創(chuàng)建線程池。
          面試官 :   Executors 定義了哪幾種 ?
          :
          • newSingleThreadExecutos   單線程線程池,也就是線程池只有一個(gè)任務(wù),這個(gè)我偶爾用一用
          • newFixedThreadPool(int nThreads)  固定大小線程的線程池
          • newCachedThreadPool()   無(wú)界線程池,這個(gè)就是無(wú)論多少任務(wù),都創(chuàng)建線程來(lái)運(yùn)行,所以隊(duì)列相當(dāng)于沒(méi)用。
          面試官 :  你上面講日常開(kāi)發(fā)自己 用 ThreadPoolExecutor 創(chuàng)建線程池,為什么不用Executors  提供的。
          :  第一是 Executors 提供的線程池使用場(chǎng)景很有限,一般場(chǎng)景很難用到,第二他們也都是通過(guò) ThreadPoolExecutor 創(chuàng)建的線程池,我直接用 ThreadPoolExecutor 創(chuàng)建線程池,可以理解原理,靈活度更高。
          參考阿里開(kāi)發(fā)手冊(cè)規(guī)約:
          4.【強(qiáng)制】線程池不允許使用Executors去創(chuàng)建,而是通過(guò)ThreadPoolExecutor的方式,這樣的處理方式讓寫(xiě)的同學(xué)更加明確線程池的運(yùn)行規(guī)則,規(guī)避資源耗盡的風(fēng)險(xiǎn)。
          說(shuō)明:Executors返回的線程池對(duì)象的弊端如下:
          1)
          FixedThreadPoolSingleThreadPool:
          ??允許的請(qǐng)求隊(duì)列長(zhǎng)度為Integer.MAX_VALUE,可能會(huì)堆積大量的請(qǐng)求,從而導(dǎo)致OOM。
          2)
          CachedThreadPool:
          ??允許的創(chuàng)建線程數(shù)量為Integer.MAX_VALUE,可能會(huì)創(chuàng)建大量的線程,從而導(dǎo)致OOM。
          《阿里巴巴研發(fā)手冊(cè)》
          面試官 :  前面你代碼里有任務(wù)入隊(duì)的操作,你一般自定義線程池,用的什么隊(duì)列?
          :  這個(gè)要看實(shí)際應(yīng)用的。
          1. 有的任務(wù)在早上8點(diǎn)和晚上6點(diǎn)都是高峰期,因此有任務(wù)尖刺,用 LinkedBlockingQueue, 這個(gè)是無(wú)界隊(duì)列,不限制任務(wù)大小的。
          2. 對(duì)于重要性沒(méi)那么高,非強(qiáng)依賴(lài)的任務(wù)用的ArrayBlockingQueue,這個(gè)是指定大小的,如果任務(wù)超出,會(huì)創(chuàng)建非核心線程執(zhí)行任務(wù)。
          面試官 :   那你怎么保證任務(wù)隊(duì)列的可用性呢?
          :  分幾個(gè)方面:
          1. 我的線程池管理器,會(huì)有一個(gè)定時(shí)任務(wù),定時(shí)檢測(cè)Map 中線程池當(dāng)前任務(wù)隊(duì)列的狀態(tài),會(huì)設(shè)置一個(gè) waterThreshold(水位線),超出水位線會(huì)有告警;
          2. 日常大促演練,會(huì)對(duì)線程池做壓測(cè),如果發(fā)生超水位情況,還會(huì)對(duì)線程按線程名做降級(jí),動(dòng)態(tài)調(diào)整核心線程數(shù)和隊(duì)列,當(dāng)然還有限流、降級(jí)等其他有段保障。
          面試官 :  那你怎么合理拆分線程池,核心任務(wù)數(shù)和任務(wù)隊(duì)列大小的呢?
          :  這個(gè)是個(gè)老生常談的問(wèn)題。
          【推薦】 了解每個(gè)服務(wù)大致的平均耗時(shí),可以通過(guò)獨(dú)立線程池配置,將較慢的服務(wù)與主線程池隔離開(kāi),不致于各服務(wù)線程同歸于盡。
          《阿里巴巴研發(fā)手冊(cè)》
          1. 按照任務(wù)的類(lèi)型,對(duì)任務(wù)做拆分,分成不同的線程池,分別命名;
          2. 區(qū)分任務(wù)的類(lèi)型,是CPU密集型還是IO密集型,CPU 可以設(shè)置約為CPU核心數(shù),上下文切換少,io密集型可以設(shè)置的大一些。
          3. 大體估算一個(gè),然后做壓測(cè),評(píng)估,另外線程池有個(gè)變量也可以參考意義:largestPoolSize,線程池達(dá)到過(guò)的最大線程任務(wù),比如你剛開(kāi)始可以把線程數(shù)設(shè)置的足夠大,壓測(cè)過(guò)后看這個(gè)參數(shù)達(dá)到的最大數(shù)值,同時(shí)參考系統(tǒng)的性能指標(biāo),cou、io、mem等。
          4. 這里還有個(gè)公式借鑒:最佳線程數(shù)目 = ((線程等待時(shí)間+線程CPU時(shí)間)/線程CPU時(shí)間 )* CPU數(shù)目
          5. 也有開(kāi)源的輔助測(cè)算線程池的合理線程數(shù)。
          面試官 :  那拒絕策略呢?了解嗎
          :  拒絕策略就是當(dāng)任務(wù)太多,超過(guò)maximumPoolSize了,只能拒絕。
          面試官 :  詳細(xì)講講
          :  拒絕的時(shí)候可以指定拒絕策略,也可以自己實(shí)現(xiàn),JDK默認(rèn)提供了四種拒絕策略.
          • AbortPolicy
            默認(rèn)拒絕策略, 直接拋RejectedExecutionException
          • DiscardPolicy
            任務(wù)直接丟棄,不拋出異常
          • CallerRunsPolicy
            由調(diào)用者來(lái)執(zhí)行被拒絕的任務(wù),比如主線程調(diào)用線程池的submit提交任務(wù),但是任務(wù)被拒絕,則主線程直接執(zhí)行。
            但是線程池如果已經(jīng)被關(guān)閉了,任務(wù)就被丟棄了。

            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            //線程池沒(méi)關(guān)閉
            if (!e.isShutdown()) {
            //直接run,沒(méi)有讓線程池來(lái)執(zhí)行
              r.run();
            }
            }

          • DiscardOldestPolicy
            丟棄隊(duì)列里等的最久的任務(wù),然后嘗試執(zhí)行被拒絕的任務(wù)。
            但是線程池如果已經(jīng)被關(guān)閉了,任務(wù)就被丟棄了

            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
              //丟棄隊(duì)列頭部任務(wù)
              e.getQueue().poll();
              //線程池嘗試執(zhí)行任務(wù)
              e.execute(r);
            }
            }

          面試官 :  那這幾種拒絕策略,你選哪一種?
          :   我選拒絕回答
          面試官 :   我選你回去等通知。

          有道無(wú)術(shù),術(shù)可成;有術(shù)無(wú)道,止于術(shù)

          歡迎大家關(guān)注Java之道公眾號(hào)


          好文章,我在看??

          瀏覽 66
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产视频高清无码 | A片在线视频免费观看 | 伊人色色综合 | 亚洲黄色视频网站在线观看 | 欧美日韩国产传媒 |