Android中的線程池
一、線程池的作用:
(1)避免線程重複創建和銷燬造成性能浪費
(2)控制線程最大併發數,避免大量線程之間相互搶佔資源造成阻塞
(3)便於對線程進行簡單的管理
二、ThreadPoolExecutor
Android的線程池來源於java的Executor(接口),其具體實現爲ThreadPoolExecutor。
接下來爲ThreadPoolExecutor,其構造方法爲:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory)
接下來介紹這上面各個參數的具體含義:
corePoolSize:核心線程數,啥爲核心線程數?一般情況下,核心線程在線程池中都是一直存活的,即使它們處於閒置狀態,除非設置ThreadPoolExecutor的allowCoreThreadTime這個屬性爲true,那麼當閒置時間超過keepAliveTime時,核心線程就會停止。
maximunPoolSize:這個是線程池中的最大線程數,當活動線程達到這個數目時,到來的任務就會被阻塞
keepAliveTime:非核心線程閒置的超時時長,超過這個時間,非核心線程就會被回收。
unit:keepAliveTime的時間單位。
workQueue:任務隊列,通過線程池的execute提交的Runnable對象會存儲到這個參數中。
threadFactory(接口):爲線程池提供創建新線程的功能,裏面唯一的方法:Thread newThread(Runnable r)。
接下來參考下AsyncTask中對ThreadPoolExecutor的配置:
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
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>(128);
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE,MAXIMUM_POOL_SIZE,KEEP_ALIVE,sThreadFactory
從上代碼可知:
(1)核心線程數爲CPU核心數減1,再和4比較取值;
原因:防止後臺任務將CPU資源完全耗盡,減掉這個1是留給主線程使用的。正常來說核心線程數應設置爲CPU核心數+1,其原因是:提高CPU的利用率。
我們需要根據任務是計算密集型(指處理這種任務時,線程不會發生阻塞,線程不阻塞就一定程度代表 CPU 一直在忙碌)或者是IO密集型(指運行該類任務時線程多會發生阻塞,一旦阻塞,CPU 就多被閒置)來設置線程池的大小。
對於計算密集型的任務,在有N 個處理器的系統上,當線程池的大小爲 N+1 時,能實現 CPU 的最優利用率。
(2)線程池最大的線程數爲CPU核心數的2N+1;(IO密集型)
(3)核心線程無超時機制,非核心線程在閒置時的超時時間爲1秒;
(4)任務隊列的容量爲128;
三、線程池的分類
主要有四類:FixedThreadPool、CachedThreadPool、ScheduledThreadPool、SingleThreadExecutor
(1)FixedThreadPool,通過Executors的newFixedThreadPool方法來創建
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads,nThreads,0L,TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
特點·裏面只有核心線程,線程數量固定。線程處於空閒狀態時,並不會被回收。所有線程都處於活動狀態的時候,新任務都會處於等待狀態。
(2)CachedThreadPool,通過Executors的newCachedThreadPool方法來創建。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
}
特點:裏面只有非核心線程,其最大線程數可以任意大。超時機制爲60S,超過這個數,線程池中的線程都會被超時停止,這個時候CachedThreadPool爲空。適合執行大量耗時比較少的任務。
(3)ScheduledThreadPool,通過Executors的newScheduledThreadPool方法來創建。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize,Integer.MAX_VALUE,0,NANOSECONDS,
new DelayedWorkQueue());
}
特點:核心線程數固定,非核心線程無限制,非核心線程一閒置馬上會被回收。
(4)SingleThreadExecutor,通過Executors的newSingleThreadExecutor方法來創建。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));
}
特點:所有任務都在同一個線程中按順序執行。
參考自《Android開發藝術探索》