Java併發基礎(2)------執行緒池

小碼農一個發表於2019-06-10

執行緒池的作用

  1. 每次建立和關閉執行緒都會需要花費時間(會引起系統上下文的切換),如果為每一個任務都建立一個執行緒,就可能會出現建立和關閉的時間大於單執行緒執行的時間,失去多執行緒的優勢。

  2. 為了避免頻繁的建立和銷燬執行緒,我們可以將建立的執行緒進行復用,使用執行緒池去維護一定活躍的執行緒,在需要使用到執行緒的時候,直接從執行緒池中取,無需重新建立,使用完也無需關閉執行緒,直接將其歸還至執行緒池中,減少這部分的效能消耗。

Executor框架

  1. 類與介面

Java併發基礎(2)------執行緒池

2.Executor框架提供以下五種建立執行緒池的靜態工廠方法

Java併發基礎(2)------執行緒池

Java併發基礎(2)------執行緒池

  • newFixedThreadPool()方法會返回一個具有固定數量執行緒的執行緒池,該執行緒池中的執行緒數量始終不變。如果有一個先的任務提交時,如果執行緒池中有空閒的執行緒則立即執行。如果沒有的話會被暫存在一個任務佇列中,等待有空閒執行緒的時候才會執行。
  • newSingleThreadPool()方法會返回一個只有一個執行緒的執行緒池。若有多餘一個的任務被提交到任務佇列中,任務會被儲存在任務佇列中。等到執行緒空閒時,按先入先出的順序執行佇列中的任務。
  • newCacheThreadPool()該方法返回一個可根據實際情況調整數量的執行緒池,執行緒池的數量不確定,如果有空閒執行緒可以複用時,會優先使用可複用的執行緒。若所有的執行緒都在工作,又有新的任務體積搜,則會建立先的執行緒處理任務,所有執行緒在當前任務執行完畢後,將返回執行緒池進行復用(注意:newCachedThreadPool()執行緒池裡面的執行緒等上個執行緒執行完成才可以複用執行緒,否則它會一直create執行緒。)
  • newSingleThreadPoolScheduledExecutor()方法,週期性的執行某個任務
  • newScheduledThreadPool()方法,該方法也返回一個ScheduledExxecutorService物件,但該執行緒可以指定執行緒數量
  1. ThreadExecutor
    Java併發基礎(2)------執行緒池

引數解析:

  • corePoolSize:指定了執行緒池中執行緒的數量。

  • maximumPoolSize:指定了執行緒池中最大的執行緒數。

  • keepAliveTime:當執行緒數超過corePoolSize時,多餘空閒執行緒的存活時間。即,超過corePoolSize的空閒執行緒,會在多長時間內,會被銷燬。

  • unit:KeepAliveTime的時間單位,使用TimeUnit類。

  • workQueue:任務佇列,被提交但尚未被執行的任務。

  • threadFactory:執行緒工廠,用於建立執行緒,一般使用預設即可。

  • handler:拒絕策略,當任務太多來不及處理,如何拒絕任務。

workQueue

  1. SynchronousQueue(直接提交的佇列,newCachedThreadPool使用該佇列),他是一個特殊的BlockingQueue,它沒有容量,每一個插入操作都需要等待一個相應的刪除操作,反之,每一個刪除操作都需要等待一個插入的操作,提交的任務不會真正的儲存,而總是將新任務提交給執行緒執行,如果沒有空閒的程式,則嘗試建立新的程式,如果程式數量已經達到最大值,則執行拒絕策略。因此,使用SynchronousQueue佇列,通常要設定很大的maximumPoolSize值,否則很容易執行拒絕策略。

  2. ArrayBlockingQueue(有界的任務佇列),ArayBlockingQueue 的建構函式必須帶一個容量引數,表示該佇列的最大容量,如下所示當使用有界的任務佇列時,若有新的任務需要執行,如果執行緒池的實際執行緒數小於corePoolSize,則會優先建立新的執行緒,若大於corePoolSize,則會將新任務加入等待佇列。若等待佇列已滿,無法加入,則在匯流排程數不大於maximumPoolSize的前提下,建立新的程式執行任務。若大於maximumPoolSize,則執行拒絕策略。可見,有界佇列僅當在任務佇列裝滿時,才可能將執行緒數提升到corePoolSize以上,換言之,除非系統非常繁忙,否則確保核心執行緒數維持在在corePoolSize。

  3. LinkedBlockingQueue(無界的任務佇列,newFixedThreadPool和newSingleThreadExecutor使用該佇列),與有界佇列相 比,除非系統資源耗盡,否則無界的任務佇列不存在任務入隊失敗的情況。當有新的任務到來,系統的執行緒數小於corePoolSize時,執行緒池會生成新的執行緒執行任務,但當系統的執行緒數達到corePoolSize後,就不會繼續增加。若後續仍有新的任務加入,而又沒有空閒的執行緒資源,則任務直接進入佇列等待。若任務建立和處理的速度差異很大,無界佇列會保持快速增長,直到耗盡系統記憶體。

  4. PriorityBlockingQueue(優先任務佇列是帶有執行優先順序的佇列),可以控制任務的執行先後順序,它是一個特殊的無界佇列。無論是有界佇列ArrayBlockingQueue,還是未指定大小的無界佇列LinkedBlockingQueue 都是按照先進先出演算法處理任務的。而PriorityBlockingQueue則可以根據任務自身的優先順序順序先後執行,在確保系統效能的同時,也能有很好的質量保證(總是確保高優先順序的任務先執行)。

handler 拒絕策略

Java併發基礎(2)------執行緒池

相關文章