線程池

線程池的優(yōu)點(diǎn):

  • 重用線程池中的線程,避免因為線程的創(chuàng)建和銷毀所帶來的性能開銷。
  • 能有效控制線程池的最大并發(fā)數(shù),避免大量的線程之間因相互搶占系統(tǒng)資源而導(dǎo)致的堵塞線程。
  • 能夠?qū)€程進(jìn)行簡單的管理,并提供定時執(zhí)行以及指定間隔循環(huán)執(zhí)行等功能。
    • 相對于AsyncTask來說,最大的優(yōu)勢在于:線程可控!比如在離開了某個頁面,提交到AsyncTask不能的任務(wù)不能撤銷,線程池可以在不需要的時候?qū)⒛硞€線程移除。

ThreadPoolExecutor的介紹

Android中的線程池概念來源于Java中的Executor,Executor是一個接口,真正的線程池的實現(xiàn)為ThreadPoolExecutor。ThreadPoolExecutor提供了一系列參數(shù)來配置線程池,通過不同的參數(shù)可以創(chuàng)建不同的線程池。

    public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue)
  • corePoolSize:核心線程數(shù)

默認(rèn)核心線程會在線程池中一直存活,即使它們處于閑置狀態(tài)??梢酝ㄟ^設(shè)置ThreadPoolExecutor的allowCoreThreadTimeOut為true,當(dāng)超過一定的閑置時間,將關(guān)閉核心池,這個時間間隔由keepAliveTime所制定。
  • maximumPoolSize:最大線程數(shù)

    當(dāng)活動線程數(shù)達(dá)到這個數(shù)值后,后續(xù)的新任務(wù)將會被阻塞。

  • keepAliveTime:非核心線程時超過時長

    超過這個時長,非核心池將會被回收。當(dāng)設(shè)置allowCoreThreadTimeOut為true時,同樣會作用于核心線程。

  • unit 時間單位

  • workQueue:任務(wù)隊列

    通過線程池execute方法提交的Runnable對象會被存儲在這個參數(shù)中。

  • threadFactory:線程工廠

    為線程池提供創(chuàng)建新線程的功能。 ThreadFactory只是一個接口,它只有一個方法:Thread new Thread(Runnable r).


典型的線程池配置

  • AsyncTask中的線程池配置:

private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 1;

private static final ThreadFactory sThreadFactory = new ThreadFactory() {
    private final AtomicInteger mCount = new AtomicInteger(1);

    public Thread newThread(Runnable r) {
        return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
    }
};

private static final BlockingQueue<Runnable> sPoolWorkQueue =
        new LinkedBlockingQueue<Runnable>(10);

/**
 * An {@link Executor} that can be used to execute tasks in parallel.
 */
public static final Executor THREAD_POOL_EXECUTOR
        = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

在不同的android本版本中,AsyncTask的線程池不同,但都大同小異,在另一個版本中的AsyncTask中是使用的CPU核心數(shù)為標(biāo)準(zhǔn)來給定核心線程數(shù)和最大線程數(shù)。

  • ImageLoad中的線程池:

/** This cache uses a single background thread to evict entries. */
final ThreadPoolExecutor executorService =
        new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());

android中提供的一些線程池:

    singleTaskExecutor = Executors.newSingleThreadExecutor();// 每次只執(zhí)行一個線程任務(wù)的線程池
    limitedTaskExecutor = Executors.newFixedThreadPool(3);// 限制線程池大小為7的線程池
    allTaskExecutor = Executors.newCachedThreadPool(); // 一個沒有限制最大線程數(shù)的線程池
    scheduledTaskExecutor = Executors.newScheduledThreadPool(3);// 一個可以按指定時間可周期性的執(zhí)行的線程池
    scheduledTaskFactoryExecutor = Executors.newFixedThreadPool(3, new ThreadFactoryTest());// 按指定工廠模式來執(zhí)行的線程池
    scheduledTaskFactoryExecutor.submit(new Runnable()
    {

        @Override
        public void run()
        {
            Log.i("KKK", "This is the ThreadFactory Test  submit Run! ! ! ");
        }
    });

線程池的案例:

使用動態(tài)代理方式創(chuàng)建建一個ThreadPoolProxyFactory ,里面提供兩種方式獲取線程池:普通線程池和下載的線程池。

public class ThreadPoolProxyFactory {
    static ThreadPoolProxy mNormalThreadPoolProxy;
    static ThreadPoolProxy mDownLoadThreadPoolProxy;

    /**
     * 得到普通線程池代理對象mNormalThreadPoolProxy
     */
    public static ThreadPoolProxy getNormalThreadPoolProxy() {
        if (mNormalThreadPoolProxy == null) {
            synchronized (ThreadPoolProxyFactory.class) {
                if (mNormalThreadPoolProxy == null) {
                    mNormalThreadPoolProxy = new ThreadPoolProxy(5, 5);
                }
            }
        }
        return mNormalThreadPoolProxy;
    }

    /**
     * 得到下載線程池代理對象mDownLoadThreadPoolProxy
     */
    public static ThreadPoolProxy getDownLoadThreadPoolProxy() {
        if (mDownLoadThreadPoolProxy == null) {
            synchronized (ThreadPoolProxyFactory.class) {
                if (mDownLoadThreadPoolProxy == null) {
                    mDownLoadThreadPoolProxy = new ThreadPoolProxy(3, 3);
                }
            }
        }
        return mDownLoadThreadPoolProxy;
    }
}

線程池代理,替線程池完成一些操作。提供了三種方法:執(zhí)行任務(wù),提交任務(wù),移除任務(wù)。

public class ThreadPoolProxy {

    ThreadPoolExecutor mExecutor;
    private int mCorePoolSize;
    private int mMaximumPoolSize;


    /**
     * @param corePoolSize    核心池的大小
     * @param maximumPoolSize 最大線程數(shù)
     */
    public ThreadPoolProxy(int corePoolSize, int maximumPoolSize) {
        mCorePoolSize = corePoolSize;
        mMaximumPoolSize = maximumPoolSize;
    }

    /**
     * 初始化ThreadPoolExecutor
     * 雙重檢查加鎖,只有在第一次實例化的時候才啟用同步機(jī)制,提高了性能
     */
    private void initThreadPoolExecutor() {
        if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) {
            synchronized (ThreadPoolProxy.class) {
                if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) {
                    long keepAliveTime = 3000;
                    TimeUnit unit = TimeUnit.MILLISECONDS;
                    BlockingQueue<Runnable> workQueue = new LinkedBlockingDeque<>();
                    ThreadFactory threadFactory = Executors.defaultThreadFactory();
                    RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();

                    mExecutor = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, keepAliveTime, unit, workQueue,
                            threadFactory, handler);
                }
            }
        }
    }
    /**
     執(zhí)行任務(wù)和提交任務(wù)的區(qū)別?
     1.有無返回值
        execute->沒有返回值
        submit-->有返回值
     2.Future的具體作用?
        1.有方法可以接收一個任務(wù)執(zhí)行完成之后的結(jié)果,其實就是get方法,get方法是一個阻塞方法
        2.get方法的簽名拋出了異常===>可以處理任務(wù)執(zhí)行過程中可能遇到的異常
     */
    /**
     * 執(zhí)行任務(wù)
     */
    public void execute(Runnable task) {
        initThreadPoolExecutor();
        mExecutor.execute(task);
    }

    /**
     * 提交任務(wù)
     */
    public Future<?> submit(Runnable task) {
        initThreadPoolExecutor();
        return mExecutor.submit(task);
    }

    /**
     * 移除任務(wù)
     */
    public void remove(Runnable task) {
        initThreadPoolExecutor();
        mExecutor.remove(task);
    }
}

具體使用:

  • 普通線程的使用:
ThreadPoolProxyFactory.getNormalThreadPoolProxy().execute(Runnable);
  • 下載線程的使用:
    ThreadPoolProxyFactory.getDownLoadThreadPoolProxy().execute(downLoadTask);
    ThreadPoolProxyFactory.getDownLoadThreadPoolProxy().remove(downLoadInfo.downLoadTask);

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容