<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>

          Java線程池面試必備:核心參數(shù)、工作流、監(jiān)控、調(diào)優(yōu)手段

          共 8270字,需瀏覽 17分鐘

           ·

          2021-09-01 15:01

          1. Java的線程池

          ① 合理使用線程池的好處

          • Java的線程池運用場景最多的并發(fā)框架,幾乎所有需要異步或者并發(fā)執(zhí)行任務(wù)的程序都可以使用線程池。
          • 合理使用線程池能帶來的好處:
          1. 降低資源消耗。 通過重復(fù)利用已經(jīng)創(chuàng)建的線程降低線程創(chuàng)建的和銷毀造成的消耗。例如,工作線程Woker會無線循環(huán)獲取阻塞隊列中的任務(wù)來執(zhí)行。
          2. 提高響應(yīng)速度。 當任務(wù)到達時,任務(wù)可以不需要等到線程創(chuàng)建就能立即執(zhí)行。
          3. 提高線程的可管理性。 線程是稀缺資源,Java的線程池可以對線程資源進行統(tǒng)一分配、調(diào)優(yōu)監(jiān)控。

          ② 線程池的工作流程

          • 一個新的任務(wù)到線程池時,線程池的處理流程如下:1.線程池判斷核心線程池里的線程是否都在執(zhí)行任務(wù)。 如果不是,創(chuàng)建一個新的工作線程來執(zhí)行任務(wù)。如果核心線程池里的線程都在執(zhí)行任務(wù),則進入下個流程。
          1. 線程池判斷阻塞隊列是否已滿。 如果阻塞隊列沒有滿,則將新提交的任務(wù)存儲在阻塞隊列中。如果阻塞隊列已滿,則進入下個流程。
          2. 線程池判斷線程池里的線程是否都處于工作狀態(tài)。 如果沒有,則創(chuàng)建一個新的工作線程來執(zhí)行任務(wù)。如果已滿,則交給飽和策略來處理這個任務(wù)。
          • 線程池的核心實現(xiàn)類是ThreadPoolExecutor類,用來執(zhí)行提交的任務(wù)。因此,任務(wù)提交到線程池時,具體的處理流程是由ThreadPoolExecutor類execute()方法去完成的。
          1. 如果當前運行的線程少于corePoolSize,則創(chuàng)建新的工作線程來執(zhí)行任務(wù)(執(zhí)行這一步驟需要獲取全局鎖)。
          2. 如果當前運行的線程大于或等于corePoolSize,而且BlockingQueue未滿,則將任務(wù)加入到BlockingQueue中。
          3. 如果BlockingQueue已滿,而且當前運行的線程小于maximumPoolSize,則創(chuàng)建新的工作線程來執(zhí)行任務(wù)(執(zhí)行這一步驟需要獲取全局鎖)。
          4. 如果當前運行的線程大于或等于maximumPoolSize,任務(wù)將被拒絕,并調(diào)用RejectExecutionHandler.rejectExecution()方法。即調(diào)用飽和策略對任務(wù)進行處理。
          • 工作線程(Worker): 線程池在創(chuàng)建線程時,會將線程封裝成工作線程Woker。Woker在執(zhí)行完任務(wù)后,不是立即銷毀而是循環(huán)獲取阻塞隊列里的任務(wù)來執(zhí)行。

          ③ 線程池的創(chuàng)建(7個參數(shù))

          • 可以通過ThreadPoolExecutor來創(chuàng)建一個線程池:
          new ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, 
           TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)
          • corePoolSize(線程池的基本大?。?/strong>
          1. 提交一個任務(wù)到線程池時,線程池會創(chuàng)建一個新的線程來執(zhí)行任務(wù)。注意: 即使有空閑的基本線程能執(zhí)行該任務(wù),也會創(chuàng)建新的線程。
          2. 如果線程池中的線程數(shù)已經(jīng)大于或等于corePoolSize,則不會創(chuàng)建新的線程。
          3. 如果調(diào)用了線程池的prestartAllCoreThreads()方法,線程池會提前創(chuàng)建并啟動所有基本線程。
          • maximumPoolSize(線程池的最大數(shù)量): 線程池允許創(chuàng)建的最大線程數(shù)。
          1. 阻塞隊列已滿,線程數(shù)小于maximumPoolSize便可以創(chuàng)建新的線程執(zhí)行任務(wù)。
          2. 如果使用無界的阻塞隊列,該參數(shù)沒有什么效果
          • workQueue(工作隊列): 用于保存等待執(zhí)行的任務(wù)的阻塞隊列。
          1. ArrayBlockingQueue: 基于數(shù)組結(jié)構(gòu)的有界阻塞隊列,按FIFO(先進先出)原則對任務(wù)進行排序。使用該隊列,線程池中能創(chuàng)建的最大線程數(shù)為maximumPoolSize。
          2. LinkedBlockingQueue: 基于鏈表結(jié)構(gòu)的無界阻塞隊列,按FIFO(先進先出)原則對任務(wù)進行排序,吞吐量高于ArrayBlockingQueue。使用該隊列,線程池中能創(chuàng)建的最大線程數(shù)為corePoolSize。靜態(tài)工廠方法 Executor.newFixedThreadPool()使用了這個隊列。
          3. SynchronousQueue: 一個不存儲元素的阻塞隊列。添加任務(wù)的操作必須等到另一個線程的移除操作,否則添加操作一直處于阻塞狀態(tài)。靜態(tài)工廠方法 Executor.newCachedThreadPool()使用了這個隊列。
          4. PriorityBlokingQueue: 一個支持優(yōu)先級無界阻塞隊列。使用該隊列,線程池中能創(chuàng)建的最大線程數(shù)為corePoolSize
          • keepAliveTime(線程活動保持時間): 線程池的工作線程空閑后,保持存活的時間。如果任務(wù)多而且任務(wù)的執(zhí)行時間比較短,可以調(diào)大keepAliveTime,提高線程的利用率。
          • unit(線程活動保持時間的單位): 可選單位有DAYS、HOURSMINUTES、毫秒、微秒、納。
          • handler(飽和策略,或者又稱拒絕策略): 當隊列和線程池都滿了,即線程池飽和了,必須采取一種策略處理提交的新任務(wù)。
          1. AbortPolicy: 無法處理新任務(wù)時,直接拋出異常,這是默認策略。
          2. CallerRunsPolicy:用調(diào)用者所在的線程來執(zhí)行任務(wù)。
          3. DiscardOldestPolicy:丟棄阻塞隊列中最靠前的一個任務(wù),并執(zhí)行當前任務(wù)。
          4. DiscardPolicy: 直接丟棄任務(wù)。
          • threadFactory: 構(gòu)建線程的工廠類
          • 總結(jié):
          1. 常用的5個,核心池、最大池、空閑時間、時間的單位、阻塞隊列;另外兩個:拒絕策略、線程工廠類
          2. 常見線程池的創(chuàng)建參數(shù)如下。PS: CachedThreadPool核心池為0,最大池為Integer.MAX_VALUE,相當于只使用了最大池;其他線程池,核心池與最大池一樣大,因此相當于只用了核心池。
          FixedThredPool: new ThreadExcutor(n, n, 0L, ms, new LinkedBlockingQueue<Runable>()
          SingleThreadExecutor: new ThreadExcutor(110L, ms, new LinkedBlockingQueue<Runable>())
          CachedTheadPool: new ThreadExcutor(0, max_valuem, 60L, s, new SynchronousQueue<Runnable>());
          ScheduledThreadPoolExcutor: ScheduledThreadPool, SingleThreadScheduledExecutor.
          1. 如果使用的阻塞隊列為無界隊列,則永遠不會調(diào)用拒絕策略,因為再多的任務(wù)都可以放在隊列中。
          2. SynchronousQueue不存儲任務(wù)的,新的任務(wù)要么立即被已有線程執(zhí)行,要么創(chuàng)建新的線程執(zhí)行。

          ④ 向線程池提交任務(wù)

          • 使用ThreadPoolEXecutor.execute()方法來提交任務(wù):
          public void execute(Runnable command) {
              // command為null,拋出NullPointerException
              if (command == null)
                  throw new NullPointerException();      
              int c = ctl.get();
              // 線程池中的線程數(shù)小于corePoolSize,創(chuàng)建新的線程
              if (workerCountOf(c) < corePoolSize) {
                  if (addWorker(command, true))// 創(chuàng)建工作線程
                      return;
                  c = ctl.get();
              }
              // 將任務(wù)添加到阻塞隊列,如果
              if (isRunning(c) && workQueue.offer(command)) {
                  int recheck = ctl.get();
                  if (! isRunning(recheck) && remove(command))
                      reject(command);
                  else if (workerCountOf(recheck) == 0)
                      addWorker(nullfalse);
              }// 阻塞隊列已滿,嘗試創(chuàng)建新的線程,如果超過maximumPoolSize,執(zhí)行handler.rejectExecution()
              else if (!addWorker(command, false))
                  reject(command);
          }

          ⑤ 線程池的五種運行狀態(tài)

          • RUNNING : 該狀態(tài)的線程池既能接受新提交的任務(wù),又能處理阻塞隊列中任務(wù)。
          • SHUTDOWN: 該狀態(tài)的線程池不能接收新提交的任務(wù),但是能處理阻塞隊列中的任務(wù)。(政府服務(wù)大廳不在允許群眾拿號了,處理完手頭的和排隊的政務(wù)就下班。)
          1. 處于 RUNNING 狀態(tài)時,調(diào)用 shutdown()方法會使線程池進入到該狀態(tài)。
          2. 注意: finalize() 方法在執(zhí)行過程中也會隱式調(diào)用shutdown()方法。
          • STOP: 該狀態(tài)的線程池不接受新提交的任務(wù),也不處理在阻塞隊列中的任務(wù),還會中斷正在執(zhí)行的任務(wù)。(政府服務(wù)大廳不再進行服務(wù)了,拿號、排隊、以及手頭工作都停止了。)
          1. 在線程池處于 RUNNING 或 SHUTDOWN 狀態(tài)時,調(diào)用 shutdownNow() 方法會使線程池進入到該狀態(tài);
          • TIDYING: 如果所有的任務(wù)都已終止,workerCount (有效線程數(shù))=0 。
          1. 線程池進入該狀態(tài)后會調(diào)用 terminated() 鉤子方法進入TERMINATED 狀態(tài)。
          • TERMINATED: 在terminated()鉤子方法執(zhí)行完后進入該狀態(tài),默認terminated()鉤子方法中什么也沒有做。

          ⑥ 線程池的關(guān)閉(shutdown或者shutdownNow方法

          • 可以通過調(diào)用線程池的shutdown或者shutdownNow方法來關(guān)閉線程池:遍歷線程池中工作線程,逐個調(diào)用interrupt方法中斷線程。
          • shutdown方法與shutdownNow的特點:
          1. shutdown方法將線程池的狀態(tài)設(shè)置為SHUTDOWN狀態(tài),只會中斷空閑的工作線程
          2. shutdownNow方法將線程池的狀態(tài)設(shè)置為STOP狀態(tài),會中斷所有工作線程,不管工作線程是否空閑。
          3. 調(diào)用兩者中任何一種方法,都會使isShutdown方法的返回值為true;線程池中所有的任務(wù)都關(guān)閉后isTerminated方法的返回值為true。
          4. 通常使用shutdown方法關(guān)閉線程池,如果不要求任務(wù)一定要執(zhí)行完,則可以調(diào)用shutdownNow方法

          2. java線程池的調(diào)優(yōu)以及監(jiān)控

          ① 線程池的調(diào)優(yōu)(線程池的合理配置)

          • 先從以下幾個角度分析任務(wù)的特性:
          1. 任務(wù)的性質(zhì): CPU 密集型任務(wù)、IO 密集型任務(wù)混合型任務(wù)
          2. 任務(wù)的優(yōu)先級: 高、中、低。
          3. 任務(wù)的執(zhí)行時間: 長、中、短。
          4. 任務(wù)的依賴性: 是否依賴其他系統(tǒng)資源,如數(shù)據(jù)庫連接。
          • 任務(wù)性質(zhì)不同的任務(wù)可以用不同規(guī)模的線程池分開處理。 可以通過 Runtime.getRuntime().availableProcessors() 方法獲得當前設(shè)備的 CPU 個數(shù)。
          1. CPU 密集型任務(wù)配置盡可能小的線程,如配置 N c p u + 1 N_{cpu}+1Ncp**u+1 個線程的線程池。
          2. IO 密集型任務(wù)則由于線程并不是一直在執(zhí)行任務(wù),則配置盡可能多的線程,如2 ? N c p u 2N_{cpu}2?Ncp**u*。
          3. 混合型任務(wù),如果可以拆分,則將其拆分成一個 CPU 密集型任務(wù)和一個 IO 密集型任務(wù)。只要這兩個任務(wù)執(zhí)行的時間相差不是太大,那么分解后執(zhí)行的吞吐率要高于串行執(zhí)行的吞吐率;如果這兩個任務(wù)執(zhí)行時間相差太大,則沒必要進行分解。
          • 優(yōu)先級不同的任務(wù)可以使用優(yōu)先級隊列 PriorityBlockingQueue 來處理,它可以讓優(yōu)先級高的任務(wù)先得到執(zhí)行。但是,如果一直有高優(yōu)先級的任務(wù)加入到阻塞隊列中,那么低優(yōu)先級的任務(wù)可能永遠不能執(zhí)行
          • 執(zhí)行時間不同的任務(wù)可以交給不同規(guī)模的線程池來處理,或者也可以使用優(yōu)先級隊列,讓執(zhí)行時間短的任務(wù)先執(zhí)行
          • 依賴數(shù)據(jù)庫連接池的任務(wù),因為線程提交 SQL 后需要等待數(shù)據(jù)庫返回結(jié)果,線程數(shù)應(yīng)該設(shè)置得較大,這樣才能更好的利用 CPU。
          • 建議使用有界隊列,有界隊列能增加系統(tǒng)的穩(wěn)定性和預(yù)警能力。可以根據(jù)需要設(shè)大一點,比如幾千。使用無界隊列,線程池的隊列就會越來越大,有可能會撐滿內(nèi)存,導(dǎo)致整個系統(tǒng)不可用。

          ② 線程池的監(jiān)控

          • 可以通過線程池提供的參數(shù)讀線程池進行監(jiān)控,有以下屬性可以使用:
          1. taskCount:線程池需要執(zhí)行的任務(wù)數(shù)量,包括已經(jīng)執(zhí)行完的、未執(zhí)行的和正在執(zhí)行的。
          2. completedTaskCount:線程池在運行過程中已完成的任務(wù)數(shù)量,completedTaskCount <= taskCount。
          3. largestPoolSize:線程池曾經(jīng)創(chuàng)建過的最大線程數(shù)量,通過這個數(shù)據(jù)可以知道線程池是否滿過。如等于線程池的最大大小,則表示線程池曾經(jīng)滿了。
          4. getPoolSize: 線程池的線程數(shù)量。如果線程池不銷毀的話,池里的線程不會自動銷毀,所以線程池的線程數(shù)量只增不減。
          5. getActiveCount:獲取活動的線程數(shù)。
          • 通過繼承線程池重寫線程池的 beforeExecuteafterExecute 和 terminated 方法,我們可以在任務(wù)執(zhí)行前,執(zhí)行后線程池關(guān)閉前干一些事情。
          • 如監(jiān)控任務(wù)的平均執(zhí)行時間,最大執(zhí)行時間最小執(zhí)行時間等。這幾個方法在線程池里是空方法,如:
          protected void beforeExecute(Thread t, Runnable r) { }

          3. Java線程池的常見問題

          1. 講講Java的線程池

          • 基礎(chǔ)講解:
          1. ThreadPoolExecutor為切入點,講解excute()方法中所體現(xiàn)的Java線程池運行流程
          2. 工作線程Worker,它的循環(huán)工作特點
          3. 如何新建線程池:7個參數(shù)(重點在阻塞隊列和飽和策略)
          • 進階:
          1. 線程池五個狀態(tài)的特點以及如何進行狀態(tài)之間的切換running、shutdownstop、tidyingterminated。
          2. 如何關(guān)閉線程:shutdown方法shutdownNow方法的特點
          3. 線程池的調(diào)優(yōu)(針對任務(wù)的不同特性 + 建議使用有界隊列
          4. 線程池的監(jiān)控參數(shù)以及可以重寫的方法

          • 兩種主要的線程池類型:普通的線程池ThreadPoolExecutor,支持延遲或周期性執(zhí)行的任務(wù)的線程池ScheduledThreadPoolExcutor。
          • 講解ThreadPoolExcutor中5個常用參數(shù)+2個不常用參數(shù),包含的三種線程池:創(chuàng)建時的參數(shù)、運行的流程、各自適合的場景。
          • 講解ScheduledThreadPoolExecutor的阻塞隊列的原理、如何更改任務(wù)的time。
          • 提供了五種定義好的線程池,都可以通過Executors工具類去調(diào)用,比如Executors.newFixedThreadPool(12)

          2. 具體的場景,如果corePoolSize為x,maximumPoolSize為y,阻塞隊列為z,第w個任務(wù)進來如何分配?

          3. 線程池如何進行調(diào)優(yōu)?

          • 線程池的調(diào)優(yōu)(針對任務(wù)的不同特性 + 建議使用有界隊列

          4. 線程池中的核心參數(shù),超過核心size怎么處理,隊列滿怎么處理,拒絕策略有哪些?(比較具體)

          來源 | blog.csdn.net/u014454538/article/details/96910729

          推薦閱讀:

          世界的真實格局分析,地球人類社會底層運行原理

          不是你需要中臺,而是一名合格的架構(gòu)師(附各大廠中臺建設(shè)PPT)

          企業(yè)IT技術(shù)架構(gòu)規(guī)劃方案

          論數(shù)字化轉(zhuǎn)型——轉(zhuǎn)什么,如何轉(zhuǎn)?

          華為干部與人才發(fā)展手冊(附PPT)

          企業(yè)10大管理流程圖,數(shù)字化轉(zhuǎn)型從業(yè)者必備!

          【中臺實踐】華為大數(shù)據(jù)中臺架構(gòu)分享.pdf

          華為的數(shù)字化轉(zhuǎn)型方法論

          華為如何實施數(shù)字化轉(zhuǎn)型(附PPT)

          超詳細280頁Docker實戰(zhàn)文檔!開放下載

          華為大數(shù)據(jù)解決方案(PPT)


          瀏覽 76
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  一区二区免费在线 | 精品国产一区二区有限公司 | 天天操综合 | 成人电影无码免费 | 俺来俺去在线3区 |