摘要:接上文線程池的原理學習簡單介紹,線程池類,繼承自構造方法提供了四種構造方法實現這里只介紹一種有必要對每個參數解釋一下池中所保存的線程數,包括空閑線程。文檔中提供了一個可以暫停和恢復的線程池例子運行原理線程池的原理學習三
接上文:java線程池的原理學習
ThreadPoolExecutor簡單介紹ThreadPoolExecutor,線程池類,繼承自 AbstractExecutorService
public class ThreadPoolExecutor extends AbstractExecutorService構造方法
ThreadPoolExecutor 提供了四種構造方法實現(這里只介紹一種):
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueueworkQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
有必要對每個參數解釋一下:
corePoolSize - 池中所保存的線程數,包括空閑線程。
maximumPoolSize - 池中允許的最大線程數。
keepAliveTime - 當線程數大于核心時,此為終止前多余的空閑線程等待新任務的最長時間。
unit - keepAliveTime 參數的時間單位。
workQueue - 執行前用于保持任務的隊列。此隊列僅保持由 execute 方法提交的 Runnable 任務。
threadFactory - 執行程序創建新線程時使用的工廠。
handler - 由于超出線程范圍和隊列容量而使執行被阻塞時所使用的處理程序。
配置規則為了便于跨大量上下文使用,此類提供了很多可調整的參數和擴展鉤子 (hook)。jdk文檔中建議在通常情況下,使用 Executors 提供的工廠方法配置,也就是提供好了的線程池。若非要手動配置,需要遵循以下規則:
核心和最大池大小ThreadPoolExecutor 將根據 corePoolSize 和 maximumPoolSize 設置的邊界自動調整池大小。當新任務在方法 execute(java.lang.Runnable) 中提交時:
1.運行的線程少于 corePoolSize,則創建新線程來處理請求,即使其他輔助線程是空閑的。
2:運行的線程多于 corePoolSize 而少于 maximumPoolSize,則把任務放進隊列,由空閑線程從隊列中取任務,僅當隊列滿時才創建新線程。
3:如果設置的 corePoolSize 和 maximumPoolSize 相同,則創建了固定大小的線程池。
4:如果將 maximumPoolSize 設置為基本的無界值(如 Integer.MAX_VALUE ),則允許池適應任意數量的并發任務。
還要注意以下兩點:
在大多數情況下,核心和最大池大小僅基于構造器來設置,不過也可以使用 setCorePoolSize(int) 和 setMaximumPoolSize(int) 進行動態更改。
當池中的線程數大于 corePoolSize 的時候,多余的線程會等待 keepAliveTime 長的時間,如果無請求可處理就自行銷毀。
創建新線程使用 ThreadFactory 創建新線程。如果沒有另外說明,則在同一個 ThreadGroup 中一律使用 Executors.defaultThreadFactory() 創建線程,并且這些線程具有相同的 NORM_PRIORITY 優先級和非守護進程狀態。通過提供不同的 ThreadFactory,可以改變線程的名稱、線程組、優先級、守護進程狀態,等等。如果從 newThread 返回 null 時 ThreadFactory 未能創建線程,則執行程序將繼續運行,但不能執行任何任務。
ThreadFactory 是線程工廠,它是一個接口:
public interface ThreadFactory { Thread newThread(Runnable r); }
ThreadPoolExecutor 中的 threadFactory 是由 Executors 工具類提供的:
public static ThreadFactory defaultThreadFactory() { return new DefaultThreadFactory(); }
static class DefaultThreadFactory implements ThreadFactory { private static final AtomicInteger poolNumber = new AtomicInteger(1); private final ThreadGroup group; private final AtomicInteger threadNumber = new AtomicInteger(1); private final String namePrefix; DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; } public Thread newThread(Runnable r) { ////創建的線程以“pool-N-thread-M”命名,N是該工廠的序號,M是線程號 Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); //設為非后臺線程 if (t.isDaemon()) t.setDaemon(false); //優先級為normal if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } }
DefaultThreadFactory 是一個靜態內部類
排隊策略前面說到,當線程池中運行的線程等于或多于 corePoolSize,則 Executor 始終首選將請求加入隊列,而不添加新的線程,將任務加入隊列有三種策略(具體參見jdk文檔)。
被拒絕的任務兩種情況下,新提交的任務將會被拒絕:
當 Executor 已經關閉
Executor 將有限邊界用于最大線程和工作隊列容量,且已經飽和
被拒絕的任務, execute 方法都將調用其 RejectedExecutionHandler 的 RejectedExecutionHandler.rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor) 方法。下面提供了四種預定義的處理程序策略:
在默認的 ThreadPoolExecutor.AbortPolicy 中,處理程序遭到拒絕將拋出運行時 RejectedExecutionException。
在 ThreadPoolExecutor.CallerRunsPolicy 中,線程調用運行該任務的 execute 本身。此策略提供簡單的反饋控制機制,能夠減緩新任務的提交速度。
在 ThreadPoolExecutor.DiscardPolicy 中,不能執行的任務將被刪除。
在 ThreadPoolExecutor.DiscardOldestPolicy 中,如果執行程序尚未關閉,則位于工作隊列頭部的任務將被刪除,然后重試執行程序(如果再次失敗,則重復此過程)。
定義和使用其他種類的 RejectedExecutionHandler 類也是可能的,但這樣做需要非常小心,尤其是當策略僅用于特定容量或排隊策略時。
鉤子方法此類提供兩個 protected 可重寫的 鉤子方法:
protected void beforeExecute(Thread t, Runnable r) { } protected void afterExecute(Runnable r, Throwable t) { }
這兩種方法分別在執行 每個任務 之前和之后調用。它們可用于操縱執行環境;注意這里是每個任務,即每次運行新任務時都會執行一遍。例如,重新初始化 ThreadLocal 、搜集統計信息或添加日志條目。此外,還可以重寫方法 terminated() 來執行 Executor 完全終止后需要完成的所有特殊處理。
如果鉤子 (hook) 或回調方法拋出異常,則內部輔助線程將依次失敗并突然終止。
jdk文檔中提供了一個可以暫停和恢復的線程池例子:
class PausableThreadPoolExecutor extends ThreadPoolExecutor { private boolean isPaused; private ReentrantLock pauseLock = new ReentrantLock(); private Condition unpaused = pauseLock.newCondition(); public PausableThreadPoolExecutor(...) { super(...); } protected void beforeExecute(Thread t, Runnable r) { super.beforeExecute(t, r); pauseLock.lock(); try { while (isPaused) unpaused.await(); } catch(InterruptedException ie) { t.interrupt(); } finally { pauseLock.unlock(); } } public void pause() { pauseLock.lock(); try { isPaused = true; } finally { pauseLock.unlock(); } } public void resume() { pauseLock.lock(); try { isPaused = false; unpaused.signalAll(); } finally { pauseLock.unlock(); } } }ThreadPoolExecutor運行原理
java線程池的原理學習(三)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64433.html
摘要:接上文線程池的原理學習二深入剖析線程池的五種狀態類中將線程狀態分為了以下五種可以接受新任務并且處理進入隊列中的任務不接受新任務,但是仍然執行隊列中的任務不接受新任務也不執行隊列中的任務所有任務中止,隊列為空,進入該狀態下的任務會執行方法方法 接上文:java線程池的原理學習(二) ThreadPoolExecutor深入剖析 線程池的五種狀態 ThreadPoolExecutor 類中...
摘要:當活動線程核心線程非核心線程達到這個數值后,后續任務將會根據來進行拒絕策略處理。線程池工作原則當線程池中線程數量小于則創建線程,并處理請求。當線程池中的數量等于最大線程數時默默丟棄不能執行的新加任務,不報任何異常。 spring-cache使用記錄 spring-cache的使用記錄,坑點記錄以及采用的解決方案 深入分析 java 線程池的實現原理 在這篇文章中,作者有條不紊的將 ja...
摘要:線程池的工作原理一個線程池管理了一組工作線程,同時它還包括了一個用于放置等待執行任務的任務隊列阻塞隊列。使用線程池可以對線程進行統一的分配和監控。線程池的注意事項雖然線程池是構建多線程應用程序的強大機制,但使用它并不是沒有風險的。 線程池的工作原理一個線程池管理了一組工作線程, 同時它還包括了一個用于放置等待執行 任務的任務隊列(阻塞隊列) 。 一個線程池管理了一組工作線程, 同時它還...
摘要:而中直接將任務交給運行再來看創建一個保存所有的結果運行任務依次取結果這里使用是為了等待運行完成,如果沒完成就會阻塞如果發生異常,則取消所有任務續線程池的原理學習二 Executor接口 如果查看jdk文檔,會發現java線程池都源自于這個超級接口Executor,但是這個接口本身比較簡單: public interface Executor { /** 在未來...
閱讀 3474·2021-09-22 15:02
閱讀 3520·2021-09-02 15:21
閱讀 2139·2019-08-30 15:55
閱讀 2784·2019-08-30 15:44
閱讀 785·2019-08-29 16:56
閱讀 2419·2019-08-23 18:22
閱讀 3347·2019-08-23 12:20
閱讀 3095·2019-08-23 11:28