線程池及增加策略和拒絕策略

ThreadPoolExecutor類實現了ExecutorService接口和Executor接口,能夠設置線程池corePoolSize,最大線程池大小,AliveTime,拒絕策略等。經常使用構造方法:
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
 
corePoolSize: 線程池維護線程的最少數量
maximumPoolSize:線程池維護線程的最大數量
keepAliveTime: 線程池維護線程所容許的空閒時間
unit: 線程池維護線程所容許的空閒時間的單位
workQueue: 線程池所使用的緩衝隊列
handler: 線程池對拒絕任務的處理策略
 
當一個任務經過execute(Runnable)方法欲添加到線程池時:
 
l  若是此時線程池中的數量小於corePoolSize,即便線程池中的線程都處於空閒狀態,也要建立新的線程來處理被添加的任務。
2  若是此時線程池中的數量等於 corePoolSize,可是緩衝隊列 workQueue未滿,那麼任務被放入緩衝隊列。
3  若是此時線程池中的數量大於corePoolSize,緩衝隊列workQueue滿,而且線程池中的數量小於maximumPoolSize,建新的線程來處理被添加的任務。
4  若是此時線程池中的數量大於corePoolSize,緩衝隊列workQueue滿,而且線程池中的數量等於maximumPoolSize,那麼經過 handler所指定的策略來處理此任務。也就是:處理任務的優先級爲:核心線程corePoolSize、任務隊列workQueue、最大線程maximumPoolSize,若是三者都滿了,使用handler處理被拒絕的任務。  
當線程池中的線程數量大於 corePoolSize時,若是某線程空閒時間超過keepAliveTime,線程將被終止。這樣,線程池能夠動態的調整池中的線程數。
handler有四個選擇:
 
ThreadPoolExecutor.AbortPolicy()
拋出java.util.concurrent.RejectedExecutionException異常 ,示例以下:
private static class Worker implements Runnable {
public void run() {
System.out.println(Thread.currentThread().getName() + " is running");
}
}
public static void main(String[] args) {
int corePoolSize = 5;
int maxPoolSize = 10;
long keepAliveTime = 5;
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(10);
 //拒絕策略1:將拋出 RejectedExecutionException.
RejectedExecutionHandler handler = 
                             new ThreadPoolExecutor.AbortPolicy();
ThreadPoolExecutor executor = new ThreadPoolExecutor
(corePoolSize, maxPoolSize, 
keepAliveTime, TimeUnit.SECONDS, 
queue, handler);
for(int i=0; i<100; i++) {
executor.execute(new Worker());
}
executor.shutdown();
}
運行結果以下:
pool-1-thread-2 is running
pool-1-thread-3 is running
Exception in thread "main" java.util.concurrent.RejectedExecutionException
pool-1-thread-1 is running
pool-1-thread-7 is running
pool-1-thread-6 is running
pool-1-thread-4 is running
pool-1-thread-9 is running
pool-1-thread-8 is running
pool-1-thread-5 is running
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1760)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:767)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:658)
at concurrent.ThreadPoolDemo.main(ThreadPoolDemo.java:33)
pool-1-thread-10 is running
處理源碼以下:
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException();
        }

 

用於被拒絕任務的處理程序,它直接在 execute 方法的調用線程中運行被拒絕的任務;若是執行程序已關閉,則會丟棄該任務。以下:
RejectedExecutionHandler handler = 
new ThreadPoolExecutor.CallerRunsPolicy();
 
運行以下:
pool-1-thread-7 is running
pool-1-thread-7 is running
pool-1-thread-7 is running
pool-1-thread-7 is running
pool-1-thread-7 is running
pool-1-thread-7 is running
pool-1-thread-2 is running
pool-1-thread-3 is running
pool-1-thread-1 is running
pool-1-thread-8 is running
main is running
main is running
main is running
pool-1-thread-4 is running
pool-1-thread-7 is running
pool-1-thread-7 is running
pool-1-thread-7 is running
處理源碼以下:
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
策略3:
RejectedExecutionHandler handler = 
new ThreadPoolExecutor.DiscardOldestPolicy();
這樣運行結果就不會有100個線程所有被執行。處理源碼以下:
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
 

 

用於被拒絕任務的處理程序,默認狀況下它將丟棄被拒絕的任務。
運行結果也不會所有執行100個線程。
源碼以下,實際就是對線程不執行操做:
    public static class DiscardPolicy implements RejectedExecutionHandler {
        /**
         * Creates a <tt>DiscardPolicy</tt>.
         */
        public DiscardPolicy() { }
 
        /**
         * Does nothing, which has the effect of discarding task r.
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }
 
 
這四種策略是獨立無關的,是對任務拒絕處理的四中表現形式。最簡單的方式就是直接丟棄任務。可是卻有兩種方式,究竟是該丟棄哪個任務,好比能夠丟棄當前將要加入隊列的任務自己(DiscardPolicy)或者丟棄任務隊列中最舊任務(DiscardOldestPolicy)。丟棄最舊任務也不是簡單的丟棄最舊的任務,而是有一些額外的處理。除了丟棄任務還能夠直接拋出一個異常(RejectedExecutionException),這是比較簡單的方式。拋出異常的方式(AbortPolicy)儘管實現方式比較簡單,可是因爲拋出一個RuntimeException,所以會中斷調用者的處理過程。除了拋出異常之外還能夠不進入線程池執行,在這種方式(CallerRunsPolicy)中任務將有調用者線程去執行。 
相關文章
相關標籤/搜索