java-執行緒池(一)
阿新 • • 發佈:2018-12-26
一、為什麼使用執行緒池
- 重用執行緒池中的使用,減少建立線和銷燬程的的資源消耗和提高效能。
- 可以對執行緒進行管理與維護
二、執行緒池的建立
執行緒池的建立可以使用Executors類中的方法建立,可以參考常用的四種執行緒池的建立,下面來看J.U.C包下的ThreadPoolExecutor,此類主要有以下構造方法:
/**第一種建立方式*/ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); } /**第二章建立方式*/ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), handler); } /**第三種建立方式*/ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler); } /**第四種建立方式*/ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, 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:核心執行緒池的大小,執行緒池建立完成之後,執行緒池中預設沒有任何執行緒。只有在有任務到達時才會建立一個執行緒去執行,直到corePoolSize。
maximumPoolSize:執行緒池中允許最大的執行緒數。
keepAliveTime:空閒執行緒等待新任務的最大存活時間。
unit:keepAliveTime的時間單位,比如TimeUnit.MILLISECONDS;TimeUnit.SECONDS; TimeUnit.MINUTES; TimeUnit.HOURS;
workQueue:阻塞佇列,當執行緒池中的執行緒大於corePoolSize時,新建的任務將會進入阻塞佇列等待執行,可以檢視常 用的阻塞佇列。
threadFactory:建立執行緒的工廠
handler:拒絕任務的處理策略。
拒絕策略:
- AbortPolicy:直接丟棄任務並丟擲RejectedExecutionException。
- CallerRunsPolicy:只要執行緒池未關閉,就會執行呼叫者執行緒中丟棄的任務,這樣會降低執行緒的效能。
- DiscardOldestPolicy:丟棄任務佇列中時間最長的任務然後嘗試提交當前的任務。
- DiscardPolicy:丟棄任務,不做任何處理。
執行緒池處理任務的規則:
- 當前執行緒池中執行緒的數目<corePoolSize,則每來一個任務,就會建立一個執行緒來執行
- 當前執行緒池中執行緒的數目>=corePoolSize,當有任務時,則會嘗試新增到阻塞佇列中,若新增成功,則會等待空閒執行緒來將其執行,若新增失敗(一般是阻塞佇列已滿),則會建立新的執行緒去執行,當然前提是不能maximumPoolSize的數量。
- 若當前執行緒池中的執行緒數量>maximumPoolSize,則執行任務拒絕策略處理
- 當前執行緒池中的執行緒數量?corePoolSize時,若某個空閒執行緒超過keepAliveTime時間,則會被丟棄,直到執行緒數量小於corePoolSize。一般情況下,核心執行緒不會被丟棄。
執行緒池中任務到達的執行流程:
執行緒池中的狀態:
- RUNNING:接收新的任務,執行任務佇列中的任務。
- SHUTDOWN:不接收新任務,但是執行任務佇列中的任務。
- STOP:不接收新任務,也不執行任務佇列中的任務,並打斷正在執行的任務。
- TIDYING:終止所有的任務,工作執行緒的數量為0,並且會執行terminated()回撥函式。
- TERMINATED:terminated()方法已執行完畢。
狀態轉換:
RUNNING -> SHUTDOWN: 在呼叫shutDown()方法時。
(RUNNING or SHUTDOWN) -> STOP:在呼叫shutDownNow()方法時。
SHUTDOWN -> TIDYING:執行緒池和阻塞佇列都為空。
STOP -> TIDYING :執行緒池為空。
TIDYING -> TERMINATED :terminated()方法執行完畢時。