1. 程式人生 > >Java執行緒池種類、區別和適用場景

Java執行緒池種類、區別和適用場景

newCachedThreadPool

  • 底層:返回ThreadPoolExecutor例項,corePoolSize0maximumPoolSizeInteger.MAX_VALUEkeepAliveTime60LunitTimeUnit.SECONDSworkQueueSynchronousQueue(同步佇列)
  • 通俗:當有新任務到來,則插入到SynchronousQueue中,由於SynchronousQueue是同步佇列,因此會在池中尋找可用執行緒來執行,若有可以執行緒則執行,若沒有可用執行緒則建立一個執行緒來執行該任務;若池中執行緒空閒時間超過指定大小,則該執行緒會被銷燬。
  • 適用:執行很多短期非同步的小程式或者負載較輕的伺服器

newFixedThreadPool

  • 底層:返回ThreadPoolExecutor例項,接收引數為所設定執行緒數量nThreadcorePoolSizenThreadmaximumPoolSizenThreadkeepAliveTime0L(不限時)unit為:TimeUnit.MILLISECONDSWorkQueue為:new LinkedBlockingQueue<Runnable>() 無解阻塞佇列
  • 通俗:建立可容納固定數量執行緒的池子,每隔執行緒的存活時間是無限的,當池子滿了就不在新增執行緒了;如果池中的所有執行緒均在繁忙狀態,對於新任務會進入阻塞佇列中
    (無界的阻塞佇列)
  • 適用:執行長期的任務,效能好很多

newSingleThreadExecutor:

  • 底層:FinalizableDelegatedExecutorService包裝的ThreadPoolExecutor例項,corePoolSize1maximumPoolSize1keepAliveTime0Lunit為:TimeUnit.MILLISECONDSworkQueue為:new LinkedBlockingQueue<Runnable>() 無解阻塞佇列
  • 通俗:建立只有一個執行緒的執行緒池,且執行緒的存活時間是無限的;當該執行緒正繁忙時,對於新任務會進入阻塞佇列中
    (無界的阻塞佇列)
  • 適用:一個任務一個任務執行的場景

NewScheduledThreadPool:

  • 底層:建立ScheduledThreadPoolExecutor例項,corePoolSize為傳遞來的引數,maximumPoolSizeInteger.MAX_VALUEkeepAliveTime0unit為:TimeUnit.NANOSECONDSworkQueue為:new DelayedWorkQueue() 一個按超時時間升序排序的佇列
  • 通俗:建立一個固定大小的執行緒池,執行緒池內執行緒存活時間無限制,執行緒池可以支援定時及週期性任務執行,如果所有執行緒均處於繁忙狀態,對於新任務會進入DelayedWorkQueue佇列中,這是一種按照超時時間排序的佇列結構
  • 適用:週期性執行任務的場景

執行緒池任務執行流程:

  1. 當執行緒池小於corePoolSize時,新提交任務將建立一個新執行緒執行任務,即使此時執行緒池中存在空閒執行緒。
  2. 當執行緒池達到corePoolSize時,新提交任務將被放入workQueue中,等待執行緒池中任務排程執行
  3. workQueue已滿,且maximumPoolSize>corePoolSize時,新提交任務會建立新執行緒執行任務
  4. 當提交任務數超過maximumPoolSize時,新提交任務由RejectedExecutionHandler處理
  5. 當執行緒池中超過corePoolSize執行緒,空閒時間達到keepAliveTime時,關閉空閒執行緒
  6. 當設定allowCoreThreadTimeOut(true)時,執行緒池中corePoolSize執行緒空閒時間達到keepAliveTime也將關閉

備註:

一般如果執行緒池任務佇列採用LinkedBlockingQueue佇列的話,那麼不會拒絕任何任務(因為佇列大小沒有限制),這種情況下,ThreadPoolExecutor最多僅會按照最小執行緒數來建立執行緒,也就是說執行緒池大小被忽略了。

如果執行緒池任務佇列採用ArrayBlockingQueue佇列的話,那麼ThreadPoolExecutor將會採取一個非常負責的演算法,比如假定執行緒池的最小執行緒數為4,最大為8所用的ArrayBlockingQueue最大為10。隨著任務到達並被放到佇列中,執行緒池中最多執行4個執行緒(即最小執行緒數)。即使佇列完全填滿,也就是說有10個處於等待狀態的任務,ThreadPoolExecutor也只會利用4個執行緒。如果佇列已滿,而又有新任務進來,此時才會啟動一個新執行緒,這裡不會因為佇列已滿而拒接該任務,相反會啟動一個新執行緒。新執行緒會執行佇列中的第一個任務,為新來的任務騰出空間。

這個演算法背後的理念是:該池大部分時間僅使用核心執行緒(4個),即使有適量的任務在佇列中等待執行。這時執行緒池就可以用作節流閥。如果擠壓的請求變得非常多,這時該池就會嘗試執行更多的執行緒來清理;這時第二個節流閥—最大執行緒數就起作用了。