ThreadPoolExecutor使用介紹

2021-08-02 15:45:58 字數 3643 閱讀 7342

為了更好的使用多執行緒,jdk提供了執行緒池供開發人員使用,目的在於減少執行緒的建立和銷毀次數,以此達到執行緒的重複利用。

其中threadpoolexecutor是執行緒池中最核心的乙個類,我們先簡單看一下這個類的繼承關係。

其中executor是執行緒池的頂級介面,介面中只定義了乙個方法  void execute(runnable command);執行緒池的操作方法都是定義子在executorservice子介面中的,所以說executorservice是執行緒池真正的介面。

threadpoolexecutor提供了四個構造方法,我們看一下引數最全的乙個建構函式;

public threadpoolexecutor(int corepoolsize,

int maximumpoolsize,

long keepalivetime,

timeunit unit,

blockingqueueworkqueue,threadfactory threadfactory,rejectedexecutionhandler handler)

函式的引數含義如下:

本節我們主要對前五個引數中的corepoolsize,maximumpoolsize及workqueue是如何配合使用做出說明(keepalivetime,unit主要對空閒執行緒的存活時間做的定義,見名知意,不再做出說明),以此來引出執行緒池的一些特性。

threadfactory和handler這兩個引數都有預設值,對於它們的用法將放到其它章節去做說明。

特性一:當池中正在執行的執行緒數(包括空閒執行緒)小於corepoolsize時,新建執行緒執行任務。

下面用實驗來說明,**如下:

public class testthreadpoolexecutor 

});try catch (interruptedexception e)

//任務2

pool.execute(new runnable()

});}

}

實驗結果如下:

實驗結果分析:

從實驗結果上可以看出,當執行任務1的執行緒(thread-1)執行完成之後,任務2並沒有去復用thread-1而是新建執行緒(thread-2)去執行任務。

特性二:當池中正在執行的執行緒數大於等於corepoolsize時,新插入的任務進入workqueue排隊(如果workqueue長度允許),等待空閒執行緒來執行。

下面用實驗來說明,**如下:

public class testthreadpoolexecutor  catch (interruptedexception e) 

}});

// 任務2

pool.execute(new runnable() catch (interruptedexception e)

}});

// 任務3

pool.execute(new runnable()

});}

}

實驗結果如下:

實驗結果分析:

從實驗結果上看,任務3會等待任務1執行完之後,有了空閒執行緒,才會執行。並沒有新建執行緒執行任務3,這時maximumpoolsize=3這個引數不起作用

特性三:當佇列裡的任務數達到上限,並且池中正在執行的執行緒數小於maximumpoolsize

對於新加入的任務,新建執行緒。

下面用實驗來說明,**如下:

public class testthreadpoolexecutor  catch (interruptedexception e) 

}});

// 任務2

pool.execute(new runnable() catch (interruptedexception e)

}});

// 任務3

pool.execute(new runnable()

});// 任務4

pool.execute(new runnable()

});}

}

實驗結果如下:

實驗結果分析:

當任務4進入佇列時發現佇列的長度已經到了上限,所以無法進入佇列排隊,而此時正在執行的執行緒數(2)小於maximumpoolsize所以新建執行緒執行該任務。

特性四:當佇列裡的任務數達到上限,並且池中正在執行的執行緒數等於maximumpoolsize

對於新加入的任務,執行拒絕策略(執行緒池預設的拒絕策略是拋異常)。

下面用實驗來說明,**如下:

public class testthreadpoolexecutor  catch (interruptedexception e) 

}});

// 任務2

pool.execute(new runnable() catch (interruptedexception e)

}});

// 任務3

pool.execute(new runnable()

});// 任務4

pool.execute(new runnable() catch (interruptedexception e)

system.out.println("-------------helloworld_004---------------" + thread.currentthread().getname());

}});

// 任務5

pool.execute(new runnable()

});}

}

實驗結果如下:

實驗結果分析:

當任務5加入時,佇列達到上限,池內執行的執行緒數達到最大,故執行預設的拒絕策略,拋異常。

本文中使用到的佇列型別雖然僅限於linkedblockingqueue這一種佇列型別,但總結出來的特性,對與常用arrayblockingqueue 和 synchronousqueue同樣適用,些許不同及三種佇列的區別,將在下個章節中說明。

最後說一點,我們作為程式設計師,研究問題還是要仔細深入一點的。當你對原理了解的有夠透徹,開發起來也就得心應手了,很多開發中的問題和疑惑也就迎刃而解了,而且在面對其他問題的時候也可做到觸類旁通。當然在開發中沒有太多的時間讓你去研究原理,開發中要以實現功能為前提,可等專案上線的後,你有大把的時間或者空餘的時間,你大可去刨根問底,深入的去研究一項技術,為覺得這對一名程式設計師的成長是很重要的事情。

ThreadPoolExecutor使用小結

記錄一下那幾個引數的理解,網上說了亂七八糟,詳細看參考文件,很詳細很明白,沒什麼好說的。corepoolsize,maximumpoolsize,keepalivetime keepalivetime workqueue queue blocksize 執行執行緒後,會判斷數量是否超出corepoo...

ThreadPoolExecutor簡單介紹

在專案中如果使用發簡訊這個功能,一般會把發簡訊這個動作變成非同步的,因為大部分情況下,簡訊到底是傳送成功或者失敗,都不能影響主流程。當然像傳送mq訊息等操作也是可以封裝成非同步操作的。如果想乙個操作變成非同步的,可以直接new thread,然後在run方法中實現業務操作即可。例如 new thre...

ThreadPoolExecutor執行緒池原始碼解讀

主要變數 private volatile int corepoolsize private volatile int maximumpoolsize private volatile int poolsize 建構函式 也就是建立類的時候,需要注入引數。public threadpoolexecu...