線程學習三:線程池ThreadPoolExecutor 與 Executors






/**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} or {@code handler} is null
     */
    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;
    }
<pre name="code" class="java">/**
     * Set containing all worker threads in pool. Accessed only when
     * holding mainLock.
     */
    private final HashSet<Worker> workers = new HashSet<Worker>();





ThreadPoolExecutor 類的邏輯處理集中在8個屬性上面,上面是8個屬性構造源碼

workers           : 線程池 ,Worker是其內部類,沒個Worder含有一個線程

corePoolSize  : 線程池中最小活動線程

maximumPoolSize  :  線程池中最大允許線程數

workQueue :  緩存隊列

keepAliveTime  : 線程池中空閒線程最大存活時間

TimeUnit : keepAliveTime的單位

threadFactory  :  新建線程時工廠類

handle : 處理被拒絕線程的處理類

執行過程,如我們上篇的圖,也如上面源碼中的英文註釋 (至於執行源碼,有點地方還沒弄通,就不寫分析了)

當新來任務的時候,

1、如果線程池小於corePoolSize , 那麼新建線程執行該任務

2、如果線程池大於等於corePoolSize , 那麼就往workQueue中添加

3、如果workQueue滿了且線程池小於maximumPoolSize ,那麼就新建線程執行任務

4、如果workQueue滿了且線程池等於maximumPoolSize  ,那麼就拒絕任務 。

至於緩存中的線程是如何執行的呢 ?

在每個新建線程中都有這麼一段等效代碼 加在原任務執行結束後:

while(  task = workQueue.poll(keepAliveTime ,TimeUnit ) ) {task.run();}

即線程執行任務完後會最大阻塞等待keepAliveTime 時間,直到從緩存隊列workQueue中獲取任務 (這段時間內稱線程爲閒置線程)。

獲取到新任務就執行,沒獲取到,那麼線程結束。

至於常見的Executors中的幾個構建對象源碼如下,大家自己理解嘍:

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }//無限緩存,有nThreads個線程能夠併發執行任務,閒置時間爲0 ,即執行完任務瞬間找不到新任務就關閉線程

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    } //無限緩存,只有一個線程順訊的執行放進來的任務,閒置時間爲0,即執行完任務瞬間找不到新任務就關閉線程

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    } //0緩存,每新來個任務都看是否有閒置線程,有就使用閒置線程執行,否則新建線程 。 線程最大閒置時間60s


一般情況上訴3個已經滿足,如果大家另有需求就自行構建嘍 。

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(5, 10,
                                    1L, TimeUnit.SECONDS,
                                    new ArrayBlockingQueue<Runnable>(5)));
    }








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章