/**
* 參數介紹:
* corePoolSize 核心線程數,指保留的線程池大小(不超過maximumPoolSize值時,線程池中最多有corePoolSize 個線程工作)。
* maximumPoolSize 指的是線程池的最大大小(線程池中最大有corePoolSize 個線程可運行)
* keepAliveTime 指的是空閒線程結束的超時時間(當一個線程不工作時,過keepAliveTime 長時間將停止該線程)。
* unit 是一個枚舉,表示 keepAliveTime 的單位(有NANOSECONDS, MICROSECONDS,
* MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS,7個可選值)。
* workQueue 表示存放任務的隊列(存放需要被線程池執行的線程隊列)。
* threadFactory - 執行程序創建新線程時使用的工廠。
* handler - 由於超出線程範圍和隊列容量而使執行被阻塞時所使用的處理程序。
*/
@Configuration
public class CustomThreadFactory {
private int corePoolSize = 3;
private int maximumPoolSize = 10;
private long keepAliveTime = 0;
/**
* 1、直接提交。工作隊列的默認選項是 SynchronousQueue,它將任務直接提交給線程而不保持它們。
* 在此,如果不存在可用於立即運行任務的線程,則試圖把任務加入隊列將失敗,
* 因此會構造一個新的線程。此策略可以避免在處理可能具有內部依賴性的請求集時出現鎖。
* 直接提交通常要求無界 maximumPoolSizes, 以避免拒絕新提交的任務。
* 當命令以超過隊列所能處理的平均數連續到達時,此策略允許無界線程具有增長的可能性。
**/
@Bean("getSynchronousQueueExecutorService")
public ExecutorService getSynchronousQueueExecutorService() {
ThreadFactory namedThreadFactory = new BasicThreadFactory.Builder().namingPattern("syn-pool-%d").daemon(true).build();
return new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
keepAliveTime, TimeUnit.MILLISECONDS,
new SynchronousQueue(), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
}
/**
* 2、無界隊列。使用無界隊列(例如,不具有預定義容量的 LinkedBlockingQueue)將導致在所有 corePoolSize 線程都忙時新任務在隊列中等待。
* 這樣,創建的線程就不會超過 corePoolSize。(因此,maximumPoolSize的值也就無效了。)當每個任務完全獨立於其他任務,即任務執行互不影響時,適合於使用無界隊列;
* 例如,在 Web頁服務器中。這種排隊可用於處理瞬態突發請求,當命令以超過隊列所能處理的平均數連續到達時,此策略允許無界線程具有增長的可能性
*/
@Bean("getLinkedBlockingQueueExecutorService")
public ExecutorService getLinkedBlockingQueueExecutorService() {
ThreadFactory namedThreadFactory = new BasicThreadFactory.Builder().namingPattern("link-pool-%d").daemon(true).build();
return new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
keepAliveTime, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(), namedThreadFactory);
}
/**
* 3、有界隊列。當使用有限的 maximumPoolSizes時,有界隊列(如 ArrayBlockingQueue)有助於防止資源耗盡,但是可能較難調整和控制。
* 隊列大小和最大池大小可能需要相互折衷:使用大型隊列和小型池可以最大限度地降低 CPU 使用率、操作系統資源和上下文切換開 銷,但是可能導致人工降低吞吐量。
* 如果任務頻繁阻塞(例如,如果它們是 I/O邊界),則系統可能爲超過您許可的更多線程安排時間。使用小型隊列通常要求較大的池大小,CPU使用率較高,但是可能遇到不可接受的調度開銷,這樣也會降低吞吐量。
*線程策略默認提供4種策略
* RejectedExecutionHandler:無法處理線程的handler
* RejectedExecutionHandler接口提供了對於拒絕任務的處理的自定方法的機會。在ThreadPoolExecutor中已經默認包含了4中策略源代碼如下
* CallerRunsPolicy(直接運行run方法):線程調用運行該任務的 execute 本身。此策略提供簡單的反饋控制機制,能夠減緩新任務的提交速度。
* 1. public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
* 2. if (!e.isShutdown()) {
* 3. r.run();
* 4. }
* 5. }
* 這個策略顯然不想放棄執行任務。但是由於池中已經沒有任何資源了,那麼就直接使用調用線程本身run方法來執行。
* AbortPolicy(拋異常):處理程序遭到拒絕將拋出運行時RejectedExecutionException
* 1. public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
* 2. throw new RejectedExecutionException();
* 3. }
* 這種策略直接拋出異常,丟棄任務。
* DiscardPolicy(直接丟棄):不能執行的任務將被刪除
* 1. public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
* 2. }
* 這種策略和AbortPolicy幾乎一樣,也是丟棄任務,只不過他不拋出異常。
* DiscardOldestPolicy(拋棄最老的線程):如果執行程序尚未關閉,則位於工作隊列頭部的任務將被刪除,然後
* 重試執行程序(如果再次失敗,則重複此過程)
* 1. public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
* 2. if (!e.isShutdown()) {
* 3. e.getQueue().poll();
* 4. e.execute(r);
* 5. }
* }
* 該策略就稍微複雜一些,在pool沒有關閉的前提下首先丟掉緩存在隊列中的最早的任務,然後重新嘗試運行該任務。這個策略需要適當小心。
*/
@Bean("getArrayBlockingQueueExecutorService")
public ExecutorService getArrayBlockingQueueExecutorService() {
ThreadFactory namedThreadFactory = new BasicThreadFactory.Builder().namingPattern("array-pool-%d").daemon(true).build();
return new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
keepAliveTime, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue(100), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
}