java線程池核心類ThreadPoolExecutor概述

2020-12-14 java技術閱讀

前言

前文JAVA中的阻塞隊列和非阻塞隊列我們介紹了常用的幾種隊列,隊列的使用很廣泛,特別是一些需要生產消費模式的場景以及需要對全局的集合進行操作的場景。今天我們來講講其中的一種應用——線程池。

有三種常見的創建線程的方法:繼承Thread類、實現Runnable接口和實現Callable接口。這些線程在運行結束後都會被虛擬機銷毀,如果線程數量多的話,頻繁的創建和銷毀線程會大大浪費時間和效率。更重要的是浪費內存,當線程執行完畢後死亡,線程對象就變成垃圾,造成GC的頻繁收集和停頓。

我們使用線程池來解決這個問題,讓線程運行完不立即銷毀,並且重複使用,繼續執行其他的任務。使用線程池來管理線程,一方面使線程的創建更加規範,可以合理控制開闢線程的數量;另一方面線程的細節管理交給線程池處理,優化了資源的開銷。

核心類

在java.util.concurrent包中我們能找到線程池的定義,其中ThreadPoolExecutor是我們線程池的核心類,我們先看下構造函數。

構造函數的參數含義:

corePoolSize:指定了線程池中的線程數量,它的數量決定了添加的任務是開闢新的線程去執行,還是放到workQueue任務隊列中去;maximumPoolSize:指定了線程池中的最大線程數量,這個參數會根據你使用的workQueue任務隊列的類型,決定線程池會開闢的最大線程數量;keepAliveTime:當線程池中空閒線程數量超過corePoolSize時,多餘的線程會在多長時間內被銷毀;unit:keepAliveTime的單位;workQueue:存放提交的任務,實現隊列的方式有:BlockingQueueLinkedBlockingQueueSynchronousQueueSynchronousQueue等,關於隊列的選擇要根據實際情況來確定;threadFactory:線程工廠,用於創建線程,一般用默認即可;handler:拒絕策略;創建線程時,為了防止資源被耗盡,任務隊列都會選擇創建有界任務隊列,但這種模式下如果出現隊列已滿且線程池創建的線程數達到最大的線程數時,就需要用拒絕策略來處理線程池「超載」的情況。jdk默認的處理方式是AbortPolicy,拋出異常阻止程序(除非是安全性要求極高,否則在大並發情況下使用這種做法不是很明智);DiscardPolicy,丟棄無法處理的任務;DiscardOledesPolicy,也是丟棄任務,只不過丟棄的是隊列最先被添加進去,馬上要執行的任務;CallerRunsPolicy,由調用者所在線程來運行任務。除了使用jdk提供的這四種策略之外,我們還可以通過實現RejectExecutionHandler來自定義拒絕策略。一般流程圖:

當線程池中線程數小於corePoolSize時,新提交的任務將創建一個新線程執行任務,即使此時線程池中存在空閒線程;當線程池中線程數達到corePoolSize時,新提交任務將被放入workQueue中,等待線程池中任務調度執行 ;當workQueue已滿,且maximumPoolSize > corePoolSize時,新提交任務會創建新線程執行任務;當workQueue已滿,且提交任務數超過maximumPoolSize,任務由RejectedExecutionHandler處理;當線程池中線程數超過corePoolSize,且超過這部分的空閒時間達到keepAliveTime時,回收這些線程;當設置allowCoreThreadTimeOut(true)時,線程池中corePoolSize範圍內的線程空閒時間達到keepAliveTime也將回收。提交線程池

兩種方式的區別:execute沒有返回值,如果不需要知道線程的結果就使用execute方法,性能比較好;submit返回一個Future對象如果想知道線程結果就使用submit提交,而且它能在主線程中通過Future的get方法捕獲線程中的異常。

關閉線程池

兩種方式的區別:shutdown不再接受新的任務,之前提交的任務等執行結束再關閉線程池;shutdownNow不再接受新的任務,試圖停止池中的任務在關閉線程池,返回所有未處理的線程List列表。

總結

線程池主要用來解決線程生命周期開銷問題和資源不足問題。通過對多個任務重複使用線程,線程創建的開銷就被分攤到多個任務上,而且由於在請求到達時線程已經存在,所以消除線程創建所帶來的延遲。這樣,就可以立即為請求服務,使應用程式響應更快。另外,通過適當的調整線程中的線程數目可以防止出現資源不足。

相關焦點

  • 【線程池】java線程池ThreadPoolExecutor
    ,                                  RejectedExecutionHandler handler)    corePoolSize 線程池維護的核心線程數。為什麼這裡說核心線程數而不是最小線程數是因為在線程池被創建後,並不會直接創建corePoolSize個線程,而是等任務到來時臨時創建。等按照需要創建了corePoolSize個線程之後,這些數量的線程即使閒置,也不會被線程池收回。這時即可以將這個值理解為線程池維護的最小線程數了。    maximumPoolSize 線程池維護的最大線程數。
  • 使用Executors,ThreadPoolExecutor,創建線程池,源碼分析理解
    = threadFactory;this.handler = handler;構造函數參數1、corePoolSize 核心線程數大小,當線程數 < corePoolSize ,會創建線程執行 runnable2、maximumPoolSize 最大線程數, 當線程數 >= corePoolSize的時候,會把 runnable
  • java中ThreadPoolExecutor常識匯總
    這篇文章主要介紹了java中ThreadPoolExecutor常識匯總,線程池技術在並發時經常會使用到,java中的線程池的使用是通過調用ThreadPoolExecutor來實現的。線程池技術在並發時經常會使用到,java中的線程池的使用是通過調用ThreadPoolExecutor來實現的。
  • 線程池管理工具 ThreadPoolExecutor 詳解
    顧名思義,是一個線程池管理工具類,該類主要提供了任務管理,線程的調度和相關的hook方法來控制線程池的狀態。並且空閒線程空閒的時間達到當前參數指定的時間時該線程就會被銷毀,如果調用過allowCoreThreadTimeOut(boolean value)方法允許核心線程過期,那麼該策略針對核心線程也是生效的;unit: 指定了keepAliveTime的單位,可以為毫秒,秒,分,小時等;workQueue: 存儲未執行的任務的隊列;threadFactory:
  • ThreadPoolExecutor創建線程池
    AbortPolicy,即丟棄任務並拋出RejectedExecutionException異常使用線程池和不使用線程的區別:差異在於使用線程池的方式是復用線程。核心線程數的設置:Nthreads=Ncpu*Ucpu*(1+w/c),其中Ncpu=CPU核心數Ucpu=cpu使用率,0~1W/C=等待時間與計算時間的比率IO
  • 深入理解 Java 線程池!
    我們在使用過程中經常會直接使用newSingleThreadExecutor(),newCachedThreadPool(),newFixedThreadPool(int Threads)等已經封裝好的線程池,但這些都是通過ThreadPoolExecutor類中通過構造函數傳入不同的參數封裝的對象,所以想要了解線程池,我們就要認真研究一下線程池中最重要的ThreadPoolExecutor類。
  • 手寫Java線程池(超詳細解說)
    ), 因為線程池自身執行也需要一個線程, 所以繼承Thread, 這樣可以在BasicThreadPool的構造方法中執行start(), run方法中執行創建線程的操作(線程池內部執行任務的線程); 創建線程取決於線程池設置的最大線程數, 核心線程數, 初始化線程數, 用戶提交的任務數;2.實現ThreadPool接口(該接口主要用於定義線程池的基本操作, 比如執行任務, 獲取線程池的一些基本屬性
  • 深入理解 Java 線程池,講解的太清晰了
    核心 API 概述Executor 框架核心 API 如下:Executor - 運行任務的簡單接口。ExecutorService - 擴展了 Executor 接口。ThreadPoolExecutor - Executor 框架最核心的類,它繼承了 AbstractExecutorService 類。ScheduledThreadPoolExecutor - ScheduledExecutorService 接口的實現,一個可定時調度任務的線程池。
  • JAVA 線程池ThreadPoolExcutor原理探究
    概論線程池(英語:thread pool):一種線程使用模式。線程過多會帶來調度開銷,進而影響緩存局部性和整體性能。而線程池維護著多個線程,等待著監督管理者分配可並發執行的任務。這避免了在處理短時間任務時創建與銷毀線程的代價。線程池不僅能夠保證內核的充分利用,還能防止過分調度。
  • Java入門 - - - 線程池的基本使用
    問題解決思路:我們可以用少量的線程保持工作且可以反覆執行任務(避免線程生命周期的損耗),這也就是要使用線程池。線程池的優點:加快響應速度(線程不必頻繁創建和銷毀);合理的利用CPU和內存這些有限資源;便於進行統一管理使用場景:比如伺服器接收大量請求時,或是開發過程中需要創建多個線程處理任務等。講解:核心類ThreadPoolExecutor。
  • Java8線程池ThreadPoolExecutor底層原理及其源碼解析
    線程池核心參數介紹下面將結合線程池中的任務提交流程加深理解.3.提交任務到線程池中的流程3.1 ThreadPoolExecutor#execute方法整體流程這裡以java.util.concurrent.ThreadPoolExecutor#execute方法為例, 畫一個簡單的圖:上圖中的worker可簡單理解為線程池中的一個線程, workers.size
  • Java中線程池,你真的會用嗎?
    到底應該如何創建一個線程池呢?Executors 是一個Java中的工具類。提供工廠方法來創建不同類型的線程池。從上圖中也可以看出,Executors的創建線程池的方法,創建出來的線程池都實現了ExecutorService接口。常用方法有以下幾個:newFiexedThreadPool(int Threads):創建固定數目線程的線程池。
  • 七個方面帶你玩轉Java線程池
    我們可以看到ThreadPoolExecutor是一個核心類,線程池的創建都離不開它,所以這裡我們通過ThreadPoolExecutor創建一個線程池。當提交一個任務到線程池時,線程池會創建一個核心線程來執行任務,即使其他空閒的核心線程能夠執行新任務也會創建新的核心線程,而等到需要執行的任務數大於線程池核心線程的數量時就不再創建,這裡也可以理解為當核心線程的數量等於線程池允許的核心線程最大數量的時候,如果有新任務來,就不會創建新的核心線程。
  • 線程池的核心參數及工作原理
    JDK中線程池的類是ThreadPoolExecutor,如果不藉助Executors.newFixedThreadPool(3)等方式創建,可以用構建函數來創建線程池,它的代碼是這樣的,public ThreadPoolExecutor(int
  • Java並發編程系列34|深入理解線程池(下)
    本文轉載自【微信公眾號:java進階架構師,ID:java_jiagoushi】經微信公眾號授權轉載,如需轉載與原文作者聯繫本文是深入理解線程池下篇:線程池介紹Executor框架接口線程池狀態線程池參數線程池創建執行過程關閉線程池其他問題任務拒絕策略線程池中的線程初始化線程池容量的動態調整線程池的監控6.
  • 「原創」Java並發編程系列33|深入理解線程池(上)
    本文轉載自【微信公眾號:java進階架構師,ID:java_jiagoushi】經微信公眾號授權轉載,如需轉載與原文作者聯繫並發編程必不可少的線程池,接下來分兩篇文章介紹線程池,本文是第一篇。= threadFactory; this.handler = handler;}corePoolSize:核心線程數量;maximumPoolSize:
  • Java之線程池的簡單介紹
    現在小編來說說線程池的代碼實現:首先,java.util.concurrent.Executors:線程池的工廠類,用來生成線程池其次,Executors類中的靜態方法:>ExecutorService接口,返回的是ExecutorService接口的實現類對象,我們可以使用ExecutorService接口接收(面向接口編程)java.util.concurrent.ExecutorService:線程池接口,用來從線程池中獲取線程,調用start方法,執行線程任務。
  • Java線程池其實看懂了也很簡單
    線程池屬於開發中常見的一種池化技術,這類的池化技術的目的都是為了提高資源的利用率和提高效率,類似的HttpClient連接池,資料庫連接池等。在沒有線程池的時候,我們要創建多線程的並發,一般都是通過繼承 Thread 類或實現 Runnable 接口或者實現 Callable 接口,我們知道線程資源是很寶貴的,而且線程之間切換執行時需要記住上下文信息,所以過多的創建線程去執行任務會造成資源的浪費而且對CPU影響較大。
  • 「技術」其實銀行就是一個Java線程池
    銀行是個線程池周末,銀行七個窗口只來了兩個值班的員工,那麼這兩個員工我們就叫做核心員工數那天由於不知道什麼原因,來銀行辦業務的人特別多,兩個員工很快就忙不過來了,那麼新來的人怎麼辦呢?談到線程池就會想到池化技術,其中最核心的思想就是把寶貴的資源放到一個池子中;每次使用都從裡面獲取,用完之後又放回池子供其他人使用,有點吃大鍋飯的意思。Java線程池有以下優點:線程是稀缺資源,不能頻繁的創建。
  • java開發基礎 線程池詳解
    前言:我們在開發中經常用會到多線程,今天來介紹一下線程池的使用。線程池簡介1.5以後引入了Executor框架,它的內部使用了線程池機制,我們常使用這個框架來創建線程池。下圖為Executor下的接口和類繼承關係:Executor框架我們常用到的包括:線程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable等Executors提供了一系列工廠方法用於創建線程池,返回的線程池都實現了ExecutorService接口。