java-線程池(二)

繼上一篇java-線程池(一)講解了線程池的好處及常用線程池,這篇解析線程池源碼。

線程池重點類如下

Executor
接口,僅execute方法,將任務放入線程池
ExecutorService
接口,繼承Executor,增加對線程的狀態獲取
Executors
類,任務提交和線程池類別選擇
ThreadPoolExecutor
類,線程池,負責對任務的調度和處理

(一)Executor

public interface Executor {  
        /**
         * 將線程放入線程池
         * @param command 要執行的異步任務
         */
        void execute(Runnable command);  
    } 

統一提供線程提交接口,所有線程池生成都必須繼承。


(二)ExecutorService

public interface ExecutorService extends Executor {  
        void shutdown();  
        boolean isShutdown();  
        boolean isTerminated();  
        <T> Future<T> submit(Callable<T> task);
        <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
            throws InterruptedException;
        // 省略部分方法  
    }
在Executor的基礎上,添加對線程的生命週期的控制(終止、喚醒等)


(三)Executors

將線程池的任務提交和執行分離,此部分是任務提交部分,提供四種基本的線程池。

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1));
    }

四種線程池對比


corePoolSize
maximumPoolSize
keepAliveTime
workQueue
newFixedThreadPool
nThreads
nThreads
0L
LinkedBlockingQueue
newSingleThreadExecutor
1 1 0L LinkedBlockingQueue
newCachedThreadPool
0 Integer.MAX_VALUE
60L SynchronousQueue
newScheduledThreadPool
corePoolSize
Integer.MAX_VALUE
0L
DelayedWorkQueue

corePoolSize:線程池維護線程的最小數量

maximumPoolSize:線程池維護的最大線程數量

keepAliveTime:線程銷燬保留時間

workQueue:使用的任務保存隊列


newFixedThreadPool定長線程,可固定最大線程數。

newSingleThreadExecutor提供單線程線程池,適合按順序執行任務。

newCachedThreadPool提供了線程銷燬緩衝期60L,最大線程數無上限,適合大量小任務執行。

newScheduledThreadPool可以延時和定期執行任務。

(四)ThreadPoolExecutor

/**
     * 核心方法,任務丟給線程池
     * @param command
     */
    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        // 如果線程數小於基本線程數,則創建線程並執行當前任務
        if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
            // 如線程數大於等於基本線程數或線程創建失敗,則將當前任務放到工作隊列中。
            if (runState == RUNNING && workQueue.offer(command)) {
                //若當前沒任何線程執行,強制開始首個線程任務
                if (runState != RUNNING || poolSize == 0)
                    ensureQueuedTaskHandled(command);
            }

            // 如果線程池不處於運行中或任務無法放入隊列,並且當前線程數量小於最大允許的線程數量,則創建一個線程執行任務。
            else if (!addIfUnderMaximumPoolSize(command))
                // 當任務無法成功接收時,按策略做異常處理
                reject(command); 
        }
    }

/**
     * 添加任務到線程池
     * @param firstTask
     * @return
     */
    private boolean addIfUnderCorePoolSize(Runnable firstTask) {
        Thread t = null;
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            //線程數未滿基本線程數且當前是運行狀態時,開啓新線程
            if (poolSize < corePoolSize && runState == RUNNING)
                t = addThread(firstTask);
        } finally {
            mainLock.unlock();
        }
        return t != null;
    }

/**
     * 給任務開啓一個線程
     * 
     * @param firstTask
     * @return
     */
    private Thread addThread(Runnable firstTask) {
        //worker代表一個線程,有對整個線程的處理,當前任務執行完,自動拿隊列任務執行
        Worker w = new Worker(firstTask);
        //工廠模式創建線程
        Thread t = threadFactory.newThread(w);
        boolean workerStarted = false;
        if (t != null) {
            if (t.isAlive()) // precheck that t is startable
                throw new IllegalThreadStateException();
            w.thread = t;
            workers.add(w);
            int nt = ++poolSize;
            //當前線程數已達最大數時,不再開啓新線程
            if (nt > largestPoolSize)
                largestPoolSize = nt;
            try {
                t.start();
                workerStarted = true;
            }
            finally {
                if (!workerStarted)
                    workers.remove(w);
            }
        }
        return t;
    }




(五)線程池學習概要

線程池的合理運用,能提升系統性能,線程池創建有四種類型,各有利弊,具體情況具體分析。

後面會有專題講解android性能優化,先準備下基本知識。

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