ThreadPoolExecutor的源碼解讀

public class ThreadPoolExecutor extends AbstractExecutorService

    ThreadPoolExecutor 繼承了ExecutorService接口的抽象實現類AbstractExecutorService,提供了四個構造方法供編碼者使用:


前面三個方法都是給定默認參數替代沒有傳遞的參數然後this調用最後一個滿參數的構造函數,源代碼如下:

[java] view plain copy
  1. public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {  
  2.         this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler);  
  3.     }  

上面這個構造方法就提供了一個默認的線程工廠和一個默認的拒絕handler。

通過ThreadPoolExecutor的構造方法得到的線程池使用方法和Executors.newFixedThreadPool()方法得到的線程池使用方式是一樣的,你可以以ExecutorService來接收它,通過ExecutorService的sumbit()方法提交你要管理的線程。

這裏再解讀一下線程工廠和拒絕handler的源碼,首先從handler開始:

    這裏的RejectedExecutionHandler是java的concurrent包下的一個接口,java對其提供了四種實現:

    它的主要負責的是在線程池內的線程都處於工作狀態時,有新的任務提交進來的處理工作。

        

    1.AbortPolicy  從名字上面就可以看到,Abort-捨棄、終止,直接設置提交進來的任務,但是它在捨棄前還拋出一個異常,這也是未提交策略參數時,使用的默認策略:

[java] view plain copy
  1. public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {  
  2.             throw new RejectedExecutionException();  
  3.         }  
[java] view plain copy
  1. /** 
  2.      * The default rejected execution handler 
  3.      */  
  4.     private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();  

    2.CallerRunsPolicy 這個策略是在線程池滿負荷時,將會一直重試將此線程任務添加到線程池中。注意,如果線程池採用此種策略,可能會導致佔用cpu的過多的時間進行重新添加操作,導致真正在線程池中需要執行的線程分不到cpu的時間片。

[java] view plain copy
  1. /** 
  2.          * Executes task r in the caller's thread, unless the executor 
  3.          * has been shut down, in which case the task is discarded. 
  4.          * @param r the runnable task requested to be executed 
  5.          * @param e the executor attempting to execute this task 
  6.          */  
  7.         public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {  
  8.             if (!e.isShutdown()) {  
  9.                 r.run();  
  10.             }  
  11.         }  

    3.DiscardPolicy  這個策略直接貼源碼吧

[java] view plain copy
  1. /** 
  2.          * Does nothing, which has the effect of discarding task r. 
  3.          * @param r the runnable task requested to be executed 
  4.          * @param e the executor attempting to execute this task 
  5.          */  
  6.         public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {  
  7.         }  

看見了嗎,註釋裏面大大的Does nothing。人家啥也不幹,方法體內就是空的。你任務沒了他都不給你提示。

    4.DiscardOldestPolicy  這個策略和上面的類似,不過它是將線程池隊列最老一個任務槍斃,然後把這個任務拉進來

[java] view plain copy
  1. /** 
  2.          * Obtains and ignores the next task that the executor 
  3.          * would otherwise execute, if one is immediately available, 
  4.          * and then retries execution of task r, unless the executor 
  5.          * is shut down, in which case task r is instead discarded. 
  6.          * @param r the runnable task requested to be executed 
  7.          * @param e the executor attempting to execute this task 
  8.          */  
  9.         public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {  
  10.             if (!e.isShutdown()) {  
  11.                 e.getQueue().poll();  
  12.                 e.execute(r);  
  13.             }  
  14.         }  

以上爲Handle java提供的實現類的解答,如果這四種不滿足使用需求,希望處理方法更加複雜一點,比如將多出來的任務放到某個地方,等這邊線程池過了高峯再去處理的話,可以自己實現RejectedExecutionHandler接口,在rejectedExecution()方法體中寫入你需要的邏輯。


接下來看看線程工廠的源碼:

    ThreadFactory也是concurrent包下的接口,貼下源碼和註釋:

[java] view plain copy
  1. /** 
  2.  * An object that creates new threads on demand.  Using thread factories 
  3.  * removes hardwiring of calls to {@link Thread#Thread(Runnable) new Thread}, 
  4.  * enabling applications to use special thread subclasses, priorities, etc. 
  5.  * 
  6.  * <p> 
  7.  * The simplest implementation of this interface is just: 
  8.  * <pre> 
  9.  * class SimpleThreadFactory implements ThreadFactory { 
  10.  *   public Thread newThread(Runnable r) { 
  11.  *     return new Thread(r); 
  12.  *   } 
  13.  * } 
  14.  * </pre> 
  15.  * 
  16.  * The {@link Executors#defaultThreadFactory} method provides a more 
  17.  * useful simple implementation, that sets the created thread context 
  18.  * to known values before returning it. 
  19.  * @since 1.5 
  20.  * @author Doug Lea 
  21.  */  
  22. public interface ThreadFactory {  
  23.   
  24.     /** 
  25.      * Constructs a new {@code Thread}.  Implementations may also initialize 
  26.      * priority, name, daemon status, {@code ThreadGroup}, etc. 
  27.      * 
  28.      * @param r a runnable to be executed by new thread instance 
  29.      * @return constructed thread, or {@code null} if the request to 
  30.      *         create a thread is rejected 
  31.      */  
  32.     Thread newThread(Runnable r);  
  33. }  

可以看到,接口內只有一個方法,newThread(),從名字和註釋都可以知道,主要功能就是創建一個新的線程。

ThreadPoolExecutor中的默認線程工廠是類Executors的一個內部類

[java] view plain copy
  1. /** 
  2.      * The default thread factory 
  3.      */  
  4.     static class DefaultThreadFactory implements ThreadFactory {  
  5.         private static final AtomicInteger poolNumber = new AtomicInteger(1);  
  6.         private final ThreadGroup group;  
  7.         private final AtomicInteger threadNumber = new AtomicInteger(1);  
  8.         private final String namePrefix;  
  9.   
  10.         DefaultThreadFactory() {  
[java] view plain copy
  1. public final native void wait(long timeout) throws InterruptedException;  

SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; } public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); if (t.isDaemon()) t.setDaemon(false); if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } }上面默認的線程工廠也就是在創建線程時,設置了線程的組,線程名和優先級。我們也可以自己去實現ThreadFactory類,創建線程。下次有機會補上代碼及測試。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章