ThreadPoolExecutor 的簡單介紹

爲何要用線程池

1. 減小建立和銷燬線程的次數
2. 防止併發訪問搶佔資源, 形成線程阻塞
3. 對線程作一些管理

線程池 ThreadPoolExecutor

總共有四個構造函數,這裏只貼出一個,由於其餘三個構造函數仍是調用這個構造函數緩存

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.acc = System.getSecurityManager() == null ?
            null :
            AccessController.getContext();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

構造函數的參數(或者能夠說建立一個線程池須要的條件)併發

1. corePoolSize(線程池基本大小)必須大於或等於0;
2. maximumPoolSize(線程池最大大小)必須大於或等於1;
3. maximumPoolSize必須大於或等於corePoolSize;
4. keepAliveTime(線程存活保持時間)必須大於或等於0;
5. workQueue(任務隊列)不能爲空;
6. threadFactory(線程工廠)不能爲空,默認爲DefaultThreadFactory類
7. handler(線程飽和策略)不能爲空,默認爲ThreadPoolExecutor.AbortPolicy。

四種不一樣類型的線程池

1.newCachedThreadPool函數

建立一個可緩存的無界線程池,該方法無參數。當線程池中的線程空閒時間超過60s則會自動回收該線程,當任務超過線程池的線程數則建立新線程。線程池的大小上限爲Integer.MAX_VALUE,可看作是無限大。this

2.newFixedThreadPool線程

建立一個固定大小的線程池,該方法可指定線程池的固定大小,對於超出的線程會在LinkedBlockingQueue隊列中等待。code

3.newSingleThreadPoolblog

建立一個只有線程的線程池,該方法無參數,全部任務都保存隊列LinkedBlockingQueue中,等待惟一的單線程來執行任務,並保證全部任務按照指定順序(FIFO或優先級)執行。隊列

4.newScheduledThreadPool資源

建立一個可定時執行或週期執行任務的線程池,該方法可指定線程池的核心線程個數。rem


向線程池中添加任務

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();
    // 若是運行的線程數小於核心線程數直接建立一個新的線程
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    // 若是核心線程所有佔用, 阻塞隊列有位置,放到隊列當中
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        // 這裏作了一個 double check
        if (! isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    // 若是阻塞隊列已滿,
        // 線程池中的線程數量小於最大線程數,則建立新的線程
        // 若是線程池中的數量等於最大線程數,調用拒絕服務
    else if (!addWorker(command, false))
        reject(command);
}

execute 方法的執行流程圖

execute方法的執行過程

相關文章
相關標籤/搜索