ThreadPoolExector(線程池)

線程池ThreadPoolExecutor的優點

1.重用線程池的線程,可以避免因爲線程的創建和銷燬所帶來的性能開銷。

2.可以控制線程池的線程最大併發數量,避免線程之間因爲互相搶佔資源而造成的阻塞。

3.能夠對線程進行簡單的管理,並提供定時執行以及間隔執行等功能。

首先簡單分析一下ThreadPoolExecutor的構成參數:

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable>workQueue,
ThreadFactory threadFactory){

}

corePoolSize 

線程池的核心線程數,默認情況下,核心線程會一直在線程池中存活下來,既是是處於閒置狀態,。如果將ThreadPoolExecutor的allowCoreThreadTImeOut屬性設置爲true,超時了核心線程也會被終止,這個時間有 keepAliveTime決定。

maximumPoolSize

線程池容納的最大線程數,當活動的線程數量達到上限後,後續的任務將會阻塞。

keepAliveTime

非核心線程可以閒置的時間,超過這個時間,非核心線程會被回收。如果如果將ThreadPoolExecutor的allowCoreThreadTImeOut屬性設置爲true,核心線程也會回收。

unit 

用於指定keepAliveTime的時間單位,只是一個枚舉,常用的有TimeUnit.MILLISECONDS,TimeUnit.SECONDS(秒),TimeUnit.MINUTES(分鐘)

workQueue

線程池中的任務隊列,通過線程池的execute()方法提交的Runnable對象會存儲在這個參數中。

threadFactory 

線程工廠,爲線程池創建新的線程,它是一個接口,只有一個方法:ThreadnewThread(Runnable)。還有一個方法RejectedExecutionHandler 是當任務隊列已滿或者無法成功執行任務時會調用,報錯的,這裏不再單獨介紹。

ThreadPoolExecutor會遵循以下原則:

1)如果線程池的線程數量沒有達到核心線程的數量,會直接啓動一個核心線程去執行任務。

2)如果線程池的線程數量已經達到或者超過核心線程池的數量,那麼任務會被插到任務隊列中排隊執行。

3)如果在步驟2中任務沒有插入到任務隊列中,說明任務隊列已經排滿,如果線程池中的線程數量沒有達到最大線程數量,會啓動一個非核心線程來執行任務。

4)如果步驟3中的線程池中的線程數量已經達到最大值,就會拒絕執行。

ThreadPoolExecutor在AsyncTask的源碼中有具體提下:

private static final int CPU_COUNT =Runtime.getRuntime().availableProcessors();
    private static final int COPE_POOL_SIZE =CPU_COUNT+1;
    private static final int MAXIMUM_POOL_SIZE =CPU_COUNT*2+1;
    private static final int KEEP_ALIVE =1;
    private static final ThreadFactory mThreadFactory = new ThreadFactory() {
        private final AtomicInteger mInteger = new AtomicInteger(1);
        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r,"AsyncTask #"+mInteger.getAndIncrement());
        }
    };
    
    private static final BlockingDeque<Runnable> mWorkQueue = new LinkedBlockingDeque<>(128);
    
    public static final Executor threadPoolExector = new ThreadPoolExecutor(COPE_POOL_SIZE,MAXIMUM_POOL_SIZE,KEEP_ALIVE, TimeUnit.SECONDS
    ,mWorkQueue,mThreadFactory);

ThreadPoolExecutor的分類


1.FixedThreadPool 

通過newFixedThreadPool方法來創建。它是一種線程數量固定的線程池,只有核心線程,線程處於空閒狀態不會回收,除非線程池關閉。並且該線程池內的核心線程沒有超時限制,任務隊列也沒有限制;

 public static ExecutorService newFixedThreadPool(int threads){
       return new ThreadPoolExecutor(threads,threads,0L,TimeUnit.SECONDS,new LinkedBlockingDeque<Runnable>());
   }

2. CachedThreadPool:

通過newCachedThreadPool方法創建,它是一種線程數量不固定的線程池,它只有沒核心線程,線程數爲Interget.MAX_VALUE,當線程池的線程都處於活動狀態時,線程池會創建新的線程來處理任務,否則會調用空閒線程處理,超時時長爲60秒。它的任務隊列相當於一個空集合,任何任務都會被執行,適合執行量大耗時較少的任務。

 public static ExecutorService newCachedThreadPool(){
        return new ThreadPoolExecutor(0,Integer.MAX_VALUE,60,TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
    }

3. ScheduledThreadPool 

通過newScheduledThreadPool方法創建,它的核心線程數量是固定的,非核心線程數量是不固定的,非核心線程空閒時立即回收。適合執行定時任務和具有固定週期的重複任務。

public static public static ScheduledExecutorService newScheduledThreadPool(int threads){
        return new ScheduledThreadPoolExecutor(threads);
    }
    
    public ScheduledThreadPoolExecutor(int corePoolSize){
        super(corePoolSize,Integer.MAX_VALUE,0,TimeUnit.NANOSECONDS,new DelayedWorkQueue());
    }

4. SingleThreadPool

通過newSingleThreadPool來創建,線程池中只有一個核心線程,所有的任務都在一個線程中按順序執行,不需要考慮同步的問題。

public static ExecutorService newSingelThreadPool(){
        return new ThreadPoolExecutor(1,1,0L,TimeUnit.SECONDS,new LinkedBlockingDeque<Runnable>());
    }

常規用法實例:

Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            //TODO
        }
    };

    public void setThreadPool(){
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
        fixedThreadPool.execute(mRunnable);
        
        ExecutorService cachedThreadPool =Executors.newCachedThreadPool();
        cachedThreadPool.execute(mRunnable);
        
        ScheduledExecutorService scheduledExecutorService =Executors.newScheduledThreadPool(4);
        //延時200毫秒執行
        scheduledExecutorService.schedule(mRunnable,200,TimeUnit.MILLISECONDS);
        //延遲10毫秒,每1000毫秒執行一次
        scheduledExecutorService.scheduleAtFixedRate(mRunnable,10,1000,TimeUnit.MILLISECONDS);
       ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
        singleThreadPool.execute(mRunnable);
    }

提供一種封裝好的ThreadPoolUtil:

public class ThreadPoolUtil {
    public final static ThreadPoolExecutor mThreadPoolExecutor;
    private final static int corePoolSize = 4;
    private final static int KEEP_ALIVE_TIME = 60 * 1000;
    private final static String CUSTOM_THREAD_NAME = "";

    static {
        mThreadPoolExecutor = new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, KEEP_ALIVE_TIME,
                TimeUnit.SECONDS, new SynchronousQueue<Runnable>(true), new CustomFactory(Thread.NORM_PRIORITY));
    }

    public static void execute(Runnable runnable) {
        mThreadPoolExecutor.execute(runnable);
    }

    public static void cancle(Runnable runnable) {
        mThreadPoolExecutor.remove(runnable);
    }

    private static class CustomFactory implements ThreadFactory {

        int mPriority;
        ThreadGroup mThreadGroup;
        private AtomicInteger mInteger = new AtomicInteger(1);

        public CustomFactory(int normal) {
            this.mPriority = normal;
            mThreadGroup = Thread.currentThread().getThreadGroup();
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread mThread = new Thread(mThreadGroup, r, CUSTOM_THREAD_NAME + mInteger.getAndIncrement(), 0);
            mThread.setPriority(mPriority);
            return mThread;
        }
    }


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