見招拆招:老油條教你如何化解大廠面試官的線程池奪命連環炮!!!

      網友投稿 840 2025-04-06

      什么是線程池?

      使用線程池的好處

      線程池的核心參數

      線程池的處理流程

      線程池的創建方式有哪些?

      常用線程池及它們的使用場景

      線程池被創建后里面有線程嗎?

      你知道有什么方法對線程池進行預熱嗎?

      線程池的狀態有哪些?

      線程池的拒絕策略有那些?

      線程池的線程數到底怎么配置?

      execute 和 submit的區別

      尾言

      什么是線程池?

      使用線程池的好處

      線程池的核心參數

      線程池的處理流程

      線程池的創建方式有哪些?

      常用線程池及它們的使用場景

      線程池被創建后里面有線程嗎?

      你知道有什么方法對線程池進行預熱嗎?

      線程池的狀態有哪些?

      線程池的拒絕策略有那些?

      線程池的線程數到底怎么配置?

      execute 和 submit的區別

      尾言

      什么是線程池?

      線程池可以理解為一個具有多個線程的線程集合.

      使用線程池的好處

      降低資源消耗。通過重復利用已創建的線程降低線程創建和銷毀造成的消耗。

      提高響應速度。當任務到達時,任務可以不需要的等到線程創建就能立即執行。

      提高線程的可管理性。線程是稀缺資源,如果無限制的創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一的分配,調優和監控。

      線程池的核心參數

      corePoolSize 核心線程數,沒達到核心線程數時,會創建新的線程。當達到核心線程數時,任務會進去隊列

      maximumPoolSize 最大線程數,可以為Integer.MAX_VALUE 21億。當達到核心線程數且隊列滿了的時候,會去創建額外的線程來執行任務,最多不超過最大線程數

      keepAliveTime 存活時間,當任務處理完成,額外的線程存活一段時間后,會自行銷毀。空閑等待時間(該參數默認對核心線程無效,當allowCoreThreadTimeOut手動設置為true時,核心線程超過存活時間后才會被銷毀)

      TimeUnit 空閑等待時間的單位

      BlockingQueue :任務進來,如果核心線程數滿了,則任務進入隊列中等待。

      ThreadFactory 線程創建工廠

      RejectExecutionHandler拒絕策略,當最大線程數滿了并且隊列也滿了的時候,如果再有任務進來就會啟用拒絕策略。

      參考源碼

      /** * Creates a new {@code ThreadPoolExecutor} with the given initial * parameters and default thread factory and rejected execution handler. * It may be more convenient to use one of the {@link Executors} factory * methods instead of this general purpose constructor. * * @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set * @param maximumPoolSize the maximum number of threads to allow in the * pool * @param keepAliveTime when the number of threads is greater than * the core, this is the maximum time that excess idle threads * will wait for new tasks before terminating. * @param unit the time unit for the {@code keepAliveTime} argument * @param workQueue the queue to use for holding tasks before they are * executed. This queue will hold only the {@code Runnable} * tasks submitted by the {@code execute} method. * @throws IllegalArgumentException if one of the following holds:
      * {@code corePoolSize < 0}
      * {@code keepAliveTime < 0}
      * {@code maximumPoolSize <= 0}
      * {@code maximumPoolSize < corePoolSize} * @throws NullPointerException if {@code workQueue} is null */ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }

      線程池的處理流程

      線程池的創建方式有哪些?

      通過Executors工具類創建指定線程池

      通過 new ThreadPoolExecutor() 自定義線程池,傳入指定參數

      常用線程池及它們的使用場景

      newFixedThreadPool():固定線程數的線程池

      public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); }

      線程池特點:

      核心線程數和最大線程數大小一樣

      沒有所謂的非空閑時間,即keepAliveTime為0

      阻塞隊列為無界隊列LinkedBlockingQueue

      缺點

      如果某任務執行時間過長,而導致大量任務堆積在阻塞隊列中,或者說在某一時刻大量任務進來則會導致機器內存使用不斷飆升,最終導致OOM

      使用場景

      newFixedThreadPool 適用于處理CPU密集型的任務,確保CPU在長期被工作線程使用的情況下,盡可能的少的分配線程,即適用執行長期的任務。

      newCachedThreadPool()

      public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue()); }

      線程池特點:

      核心線程數為0

      最大線程數為Integer.MAX_VALUE

      阻塞隊列是SynchronousQueue

      非核心線程空閑存活時間為60秒

      缺點

      如果任務的提交速度大于線程處理任務的速度,那么就會不斷地創建新線程極端情況下會耗盡CPU和內存資源

      CachedThreadPool允許創建的線程數量為 Integer.MAX_VALUE ,可能會創建大量線程,從而導致 OOM。

      任務隊列采用的是SynchronousQueue,這個隊列是無法插入任務的,一有任務立即執行

      使用場景

      適用于并發執行大量短期的小任務。

      newSingleThreadExecutor()

      public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue())); }

      線程池特點

      核心線程數為1

      最大線程數也為1

      阻塞隊列是LinkedBlockingQueue

      keepAliveTime為0

      缺點

      見招拆招:老油條教你如何化解大廠面試官的線程池奪命連環炮!!!

      LinkedBlockingQueue 為無界隊列,可能會導致OOM

      使用場景

      適用于串行執行任務的場景,一個任務一個任務地執行。

      newScheduledThreadPool()

      public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); }

      線程池特點

      最大線程數為Integer.MAX_VALUE

      阻塞隊列是DelayedWorkQueue

      keepAliveTime為0

      scheduleAtFixedRate() :按某種速率周期執行

      scheduleWithFixedDelay():在某個延遲后執行

      使用場景

      周期性執行任務的場景,需要限制線程數量的場景

      線程池被創建后里面有線程嗎?

      線程池被創建后如果沒有任務過來,是不會有線程的。

      你知道有什么方法對線程池進行預熱嗎?

      ==線程預熱可以使用以下兩個方法==

      1.只啟動一個線程預熱

      2.全部啟動預熱

      線程池的狀態有哪些?

      參考源碼

      //記錄線程池的狀態,已經線程池中線程的個數,初始化狀態為 Running private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); //線程池的五種狀態 private static final int RUNNING = -1 << COUNT_BITS; private static final int SHUTDOWN = 0 << COUNT_BITS; private static final int STOP = 1 << COUNT_BITS; private static final int TIDYING = 2 << COUNT_BITS; private static final int TERMINATED = 3 << COUNT_BITS;

      1、RUNNING

      狀態說明:線程池處在RUNNING狀態時,能夠接收新任務,以及對已添加的任務進行處理。

      狀態切換:線程池的初始化狀態是RUNNING。換句話說,線程池被一旦被創建,就處于RUNNING狀態,并且線程池中的任務數為0!

      2、ShutDown

      狀態說明:線程池處在SHUTDOWN狀態時,不接收新任務,但能處理已添加的任務。

      狀態切換:調用線程池的shutdown() 時,線程池由RUNNING -> SHUTDOWN。

      3、STOP

      狀態說明:線程池處在STOP狀態時,不接收新任務,不處理已添加的任務,并且會中斷正在處理的任務。

      狀態切換:調用線程池的shutdownNow() 時,線程池由(RUNNING or SHUTDOWN ) -> STOP。

      4、tidying

      狀態說明:當所有的任務已終止,ctl記錄的”任務數量”為0,線程池會變為TIDYING狀態。

      當線程池變為TIDYING狀態時,會執行鉤子函數terminated()。terminated()在ThreadPoolExecutor類中是空的,若用戶想在線程池變為TIDYING時,進行相應的處理;可以通過重載terminated()函數來實現。

      狀態切換:當線程池在SHUTDOWN狀態下,阻塞隊列為空并且線程池中執行的任務也為空時,就會由 SHUTDOWN -> TIDYING。當線程池在STOP狀態下,線程池中執行的任務為空時,就會由STOP -> TIDYING。

      5、 TERMINATED(terminated)

      狀態說明:線程池徹底終止,就變成TERMINATED狀態。

      狀態切換:線程池處在TIDYING狀態時,執行完terminated()之后,就會由 TIDYING -> TERMINATED。

      線程池的拒絕策略有那些?

      AbortPolicy(默認),直接拋出一個類型為 RejectedExecutionException 的 RuntimeException異常阻止系統的正常運行。

      DiscardPolicy:直接丟棄任務,不給予任何處理也不拋出異常。如果允許任務丟失的話,這是最好的方案。

      DiscardOldestPolicy,拋棄隊列中等待時間最長的任務,然后把當前任務加入隊列中嘗試再次提交任務。

      CallerRunsPolicy:"調用者運行"一種調節機制,該策略既不會拋棄任務也不會拋出異常,而是將某些任務回退到調用者,從而降低新任務的流量。

      線程池的線程數到底怎么配置?

      判斷當前任務是CPU 密集型還是 IO 密集型

      公式

      CPU 密集型任務(N+1): 這種任務消耗的主要是 CPU 資源,可以將線程數設置為 N(CPU 核心數)+1,比 CPU 核心數多出來的一個線程是為了防止線程偶發的缺頁中斷,或者其它原因導致的任務暫停而帶來的影響。 一旦任務暫停,CPU 就會處于空閑狀態,而在這種情況下多出來的一個線程就可以充分利用 CPU 的空閑時間。

      I/O 密集型任務(2N): 這種任務應用起來,系統會用大部分的時間來處理 I/O 交互,而線程在處理 I/O 的時間段內不會占用 CPU 來處理,這時就可以將 CPU 交出給其它線程使用。因此在 I/O 密集型任務的應用中,我們可以多配置一些線程,具體的計算方法是 2N。

      execute 和 submit的區別

      1. 方法來源不同

      execut()是在線程池的頂級接口Executor中定義的,而且只有這一個接口,可見這個方法的重要性。

      public interface Executor { void execute(Runnable command); }

      在ThreadPoolExecutor類中有它的具體實現。

      submit()是在ExecutorService接口中定義的,并定義了三種重載方式,具體可以查看JDK文檔

      Future submit(Callable task); Future submit(Runnable task); Future submit(Runnable task, T result);

      2. 接受參數不同

      execute()方法只能接收實現Runnable接口類型的任務

      submit()方法則既可以接收Runnable類型的任務,也可以接收Callable類型的任務。

      3. 返回值不同

      execute()的返回值是void,線程提交后不能得到線程的返回值。

      submit()的返回值是Future,通過Future的get()方法可以獲取到線程執行的返回值,get()方法是同步的,執行get()方法時,如果線程還沒執行完,會同步等待,直到線程執行完成。

      雖然submit()方法可以提交Runnable類型的參數,但執行Future方法的get()時,線程執行完會返回null,不會有實際的返回值,這是因為Runable本來就沒有返回值

      4. 對于異常處理不同

      execute在執行任務時,如果遇到異常會直接拋出,

      而submit不會直接拋出,只有在調用Future的get方法獲取返回值時,才會拋出異常。

      尾言

      我是 Code皮皮蝦,未來的日子里會不斷更新出對大家有益的博文,期待大家的關注!!!

      創作不易,如果這篇博文對各位有幫助,希望各位小伙伴可以==和關注我哦==,感謝支持,我們下次再見~~~

      ==分享大綱==

      大廠面試題專欄

      Java從入門到入墳學習路線目錄索引

      開源爬蟲實例教程目錄索引

      更多精彩內容分享,請點擊 Hello World (●’?’●)

      任務調度

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:生成數據透視表,源數據更新后,如何讓數據透視表隨之更新?(透視表中如何更新數據源)
      下一篇:FPGA之道(60)時空變換之空域優化
      相關文章
      精品亚洲av无码一区二区柚蜜| 亚洲五月六月丁香激情| 亚洲国产国产综合一区首页| 丁香五月亚洲综合深深爱| 亚洲AV女人18毛片水真多| 亚洲国产成a人v在线观看| 亚洲一区二区三区在线观看蜜桃 | 亚洲AV无码资源在线观看| 久久国产亚洲精品| 亚洲午夜在线播放| 亚洲国产成人在线视频| 亚洲国产成人手机在线电影bd| 亚洲国产精品线观看不卡| 亚洲国产精品久久网午夜 | 亚洲国产成人爱av在线播放| 国产青草亚洲香蕉精品久久| 国产亚洲精品美女久久久久 | 亚洲av无码成人精品区一本二本| 亚洲欧美日韩一区二区三区在线| 亚洲色偷偷偷综合网| 亚洲精品无码永久在线观看男男| 亚洲黄页网在线观看| 亚洲中文无码mv| 亚洲精品无码中文久久字幕| 狼人大香伊蕉国产WWW亚洲| 亚洲av日韩专区在线观看| 午夜亚洲国产理论片二级港台二级 | 国产成人亚洲午夜电影| mm1313亚洲精品无码又大又粗 | 99人中文字幕亚洲区| 亚洲国产精品综合福利专区| 亚洲剧场午夜在线观看| 亚洲国产91在线| 蜜芽亚洲av无码一区二区三区| 内射无码专区久久亚洲| 亚洲乱码国产一区网址| 亚洲人成网77777色在线播放 | 国产精品亚洲一区二区三区在线观看 | 亚洲第一黄色网址| 久久影视综合亚洲| 婷婷亚洲综合五月天小说|