1. 程式人生 > >使用執行緒池來建立執行緒

使用執行緒池來建立執行緒

1.如何使用執行緒池來建立執行緒?

java中提供了一個靜態工廠方法來建立不同的執行緒池:  Executors

通過靜態方法創建出的執行緒都實現了ExecutorService介面。常用的方法包括:

newFixedThreadPool(int threads); 建立一個固定數目的執行緒池

newCachedThreadPool(); 建立一個可快取的執行緒池,呼叫execute方法將重用以前建立的執行緒,如果沒有可用執行緒則建立一個新的執行緒並新增到池中。終止並移除那些已經存在60s未被使用的執行緒。

newSingleThreadPoolExcutor() 建立一個單執行緒化的Excutor

newScheduledThreadPool(int corePoolSize) 建立一個定時及週期性執行任務的執行緒池。

例項: 線上程的基本介紹中有具體的使用方法:

 

2. 為什麼不推薦使用jdk自帶的executors的方式來建立執行緒池?

在阿里巴巴java開發手冊中明確規定不允許使用Executors建立執行緒池。

檢視JDK原始碼:

可以看到實現是例項化一個ThreadPoolExecutor,建立的阻塞佇列為new LinkedBlockQueue。

java中的阻塞佇列有兩種 ArrayBlockingQueue LinkedBlockingQueue.

ArrayBlockingQueue是一個以陣列設計的有界佇列,必須設定大小

LinkedBlockingQueue 是一個以連結串列實現的有界阻塞佇列,容量可以選擇設定,不設定的話是無界的最大長度為Integer.MAX_VALUE。

所以說Executors建立執行緒池沒有傳入阻塞佇列的長度,阻塞佇列就是一個無邊界佇列,對於一個無邊界佇列來說是可以向其中無限新增任務的,這種情況下可能由於任務數太多而導致記憶體溢位。

FixedThreadPool和SingleThreadPool允許等待的請求佇列是Integer.MAX_VALUE 可能導致記憶體溢位。 而CachedThreadPool和shceduledThreadPool允許建立的執行緒數量是Integer.MAX_VALUE 同樣會出現記憶體溢位。

 

建立執行緒池的正確方式:

避免使用Executors建立執行緒池主要是為了避免其中的預設實現,可以改用ThreadPoolExecutor構造方法指定引數即可。

需要指定核心執行緒池的大小、最大執行緒池的數量、保持存活的時間、等待佇列容量的大小。在這種情況下一旦提交的執行緒數超過當前可用的執行緒數時就會丟擲拒絕執行的異常 java.util.concurrent.RejectedExecutionException 有界佇列已經滿了便無法處理新的任務。

 

使用工具類來建立執行緒池:

除了自己定義的ThreadPool之外,還可以使用開源庫 apache guava等。

個人推薦使用guava的ThreadFactoryBuilder() 來建立執行緒池:

使用上面的方法建立執行緒池不僅可以避免OOM的問題,還可以自定義執行緒名稱,更加方便出錯時溯源。