線程池的優(yōu)點:
- 重用線程池中的線程夏伊,避免因為線程的創(chuàng)建和銷毀所帶來的性能開銷许师。
- 能有效控制線程池的最大并發(fā)數屏轰,避免大量的線程之間因相互搶占系統(tǒng)資源而導致的堵塞線程铜靶。
- 能夠對線程進行簡單的管理叔遂,并提供定時執(zhí)行以及指定間隔循環(huán)執(zhí)行等功能。
- 相對于AsyncTask來說争剿,最大的優(yōu)勢在于:線程可控已艰!比如在離開了某個頁面,提交到AsyncTask不能的任務不能撤銷秒梅,線程池可以在不需要的時候將某個線程移除旗芬。
ThreadPoolExecutor的介紹
Android中的線程池概念來源于Java中的Executor,Executor是一個接口捆蜀,真正的線程池的實現為ThreadPoolExecutor疮丛。ThreadPoolExecutor提供了一系列參數來配置線程池,通過不同的參數可以創(chuàng)建不同的線程池辆它。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
-
corePoolSize:核心線程數
默認核心線程會在線程池中一直存活誊薄,即使它們處于閑置狀態(tài)∶誊裕可以通過設置ThreadPoolExecutor的allowCoreThreadTimeOut為true呢蔫,當超過一定的閑置時間,將關閉核心池飒筑,這個時間間隔由keepAliveTime所制定片吊。
-
maximumPoolSize:最大線程數
當活動線程數達到這個數值后,后續(xù)的新任務將會被阻塞协屡。
-
keepAliveTime:非核心線程時超過時長
超過這個時長俏脊,非核心池將會被回收。當設置allowCoreThreadTimeOut為true時肤晓,同樣會作用于核心線程爷贫。
-
unit 時間單位
-
workQueue:任務隊列
通過線程池execute方法提交的Runnable對象會被存儲在這個參數中认然。
-
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核心數為標準來給定核心線程數和最大線程數毕骡。
-
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í)行一個線程任務的線程池
limitedTaskExecutor = Executors.newFixedThreadPool(3);// 限制線程池大小為7的線程池
allTaskExecutor = Executors.newCachedThreadPool(); // 一個沒有限制最大線程數的線程池
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í)行任務,提交任務,移除任務。
public class ThreadPoolProxy {
ThreadPoolExecutor mExecutor;
private int mCorePoolSize;
private int mMaximumPoolSize;
/**
* @param corePoolSize 核心池的大小
* @param maximumPoolSize 最大線程數
*/
public ThreadPoolProxy(int corePoolSize, int maximumPoolSize) {
mCorePoolSize = corePoolSize;
mMaximumPoolSize = maximumPoolSize;
}
/**
* 初始化ThreadPoolExecutor
* 雙重檢查加鎖,只有在第一次實例化的時候才啟用同步機制,提高了性能
*/
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í)行任務和提交任務的區(qū)別?
1.有無返回值
execute->沒有返回值
submit-->有返回值
2.Future的具體作用?
1.有方法可以接收一個任務執(zhí)行完成之后的結果,其實就是get方法,get方法是一個阻塞方法
2.get方法的簽名拋出了異常===>可以處理任務執(zhí)行過程中可能遇到的異常
*/
/**
* 執(zhí)行任務
*/
public void execute(Runnable task) {
initThreadPoolExecutor();
mExecutor.execute(task);
}
/**
* 提交任務
*/
public Future<?> submit(Runnable task) {
initThreadPoolExecutor();
return mExecutor.submit(task);
}
/**
* 移除任務
*/
public void remove(Runnable task) {
initThreadPoolExecutor();
mExecutor.remove(task);
}
}
具體使用:
- 普通線程的使用:
ThreadPoolProxyFactory.getNormalThreadPoolProxy().execute(Runnable);
- 下載線程的使用:
ThreadPoolProxyFactory.getDownLoadThreadPoolProxy().execute(downLoadTask);
ThreadPoolProxyFactory.getDownLoadThreadPoolProxy().remove(downLoadInfo.downLoadTask);