Android線程和線程池
- Android中的線程操作相關(guān)的類有
AsyncTask IntentService HandleThread
-
AsyncTask
AsyncTask必須在主線程中初始化
Android 3.0開始 AsyncTask默認(rèn)使用串行方式執(zhí)行任務(wù)隊(duì)列惹盼,即單線程串行簿训,但可定制線程池并行執(zhí)行通過executOnExecutor()傲宜。
主要是SerialExcutor負(fù)責(zé)任務(wù)的排隊(duì)星立,THREAD_POOL_EXCUTOR負(fù)責(zé)真正的任務(wù)執(zhí)行经瓷。
executor()方法必須在UI線程中執(zhí)行
一個(gè)AsyncTask對象只能執(zhí)行一次痹届,否則會(huì)報(bào)錯(cuò)
AsyncTask中有用到抽象工廠模式(多線程環(huán)境下工廠類創(chuàng)建線程)
AsyncTask中對任務(wù)包裝主要是FutureTask
FutureTask可用于異步獲取執(zhí)行結(jié)果或取消執(zhí)行任務(wù)的場景魄眉。通過傳入Runnable或者Callable的任務(wù)給FutureTask鬼廓,直接調(diào)用其run方法或者放入線程池執(zhí)行晰奖,之后可以在外部通過FutureTask的get方法異步獲取執(zhí)行結(jié)果谈撒,因此,F(xiàn)utureTask非常適合用于耗時(shí)的計(jì)算匾南,主線程可以在完成自己的任務(wù)后啃匿,再去獲取結(jié)果。另外蛆楞,F(xiàn)utureTask還可以確保即使調(diào)用了多次run方法溯乒,它都只會(huì)執(zhí)行一次Runnable或者Callable任務(wù),或者通過cancel取消FutureTask的執(zhí)行等豹爹。
-
HandleThread
繼承自Thread,主要是內(nèi)部創(chuàng)建了Looper裆悄,關(guān)聯(lián)Looper,不用手動(dòng)創(chuàng)建Thread中prepare Looper和loop了臂聋。
-
IntentService
一個(gè)抽象類光稼,繼承自Service
適用于執(zhí)行后臺耗時(shí)任務(wù)崖技,任務(wù)停止后,Service自動(dòng)停止
由于它是服務(wù)钟哥,它比其他線程優(yōu)先級高很多迎献,不容易被系統(tǒng)kill
內(nèi)部它封裝了HandlerThread 和Handler,從onCreate中可以看得出
@Override
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
- IntentSerivce 通過調(diào)用startService傳遞Intent到onStartCommand,onStartCommand會(huì)通過Handle發(fā)送Message至IntentService內(nèi)部的HandleThread中腻贰,根據(jù)Intent
中攜帶的參數(shù)吁恍,調(diào)用重寫的onHandleIntent處理任務(wù),onHandleIntent執(zhí)行完畢后播演,執(zhí)行stopSelf(startId)
這里為何調(diào)用stopSelf(startId) 它與stopSelf()區(qū)別
stopSelf(startId)不會(huì)立即停止當(dāng)前Serivce,而是等待所有Intent都執(zhí)行完畢后才會(huì)終止服務(wù)冀瓦,每調(diào)用一次startService(Intent)都會(huì)調(diào)用一次onStartCommand傳遞Intent。
stopSelf()會(huì)立即停止服務(wù)
- 因?yàn)镮ntentService內(nèi)部HandleThread的消息機(jī)制写烤,所以翼闽,傳遞給IntentService的Intent任務(wù)也是順序執(zhí)行的。
Android中的線程池
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory)
corePoolSize: 核心線程數(shù)洲炊,默認(rèn)情況下一直存活的線程感局,即使空閑狀態(tài)下,如果將ThreadPoolExecutor的allowCoreThreadTimeOut屬性設(shè)置為true暂衡,則閑置的線程在等待新任務(wù)到來時(shí)會(huì)有超時(shí)策略询微,超時(shí)時(shí)間由keepAliveTime來決定,當(dāng)超時(shí)后狂巢,核心線程就會(huì)被終止
maximumPoolSize: 線程池所能容納的最大線程數(shù)撑毛,當(dāng)活動(dòng)線程數(shù)達(dá)到這個(gè)數(shù)值后,后續(xù)的新任務(wù)將會(huì)被阻塞
keepAliveTime:非核心線程線程閑置時(shí)間超時(shí)時(shí)長唧领。超過這個(gè)時(shí)長藻雌,線程將會(huì)被回收
unit:指定keepAliveTime所用的時(shí)間單位
workQueue:線程池中的任務(wù)隊(duì)列,通過execute提交的Runnable對象會(huì)存儲在這個(gè)隊(duì)列中斩个。
threadFactory:線程工廠胯杭,為線程池創(chuàng)建新的線程,為一個(gè)接口萨驶。
- ThreadpoolExecutor 執(zhí)行任務(wù)大致規(guī)則:
- 如果線程池中的核心線程數(shù)未達(dá)到核心線程的數(shù)量歉摧,那么會(huì)啟動(dòng)核心線程來執(zhí)行任務(wù)艇肴。
- 如果線程池中的線程數(shù)量已經(jīng)達(dá)到或超過核心線程數(shù)量腔呜,那么新來的任務(wù)會(huì)被插入到任務(wù)隊(duì)列中排隊(duì)等待執(zhí)行
- 如果在步驟2中無法將任務(wù)插入到任務(wù)隊(duì)列,這是由于任務(wù)隊(duì)列已經(jīng)滿了再悼,這個(gè)時(shí)候如果線程數(shù)量未達(dá)到線程池規(guī)定的最大數(shù)量核畴,那么會(huì)立刻啟動(dòng)一個(gè)非核心線程來執(zhí)行任務(wù)。
- 如果步驟3中的線程數(shù)量已經(jīng)達(dá)到線程池的最大值冲九,則拒絕此任務(wù)谤草,ThreadPoolExecutor會(huì)調(diào)用RejectedExecutionHandler的rejectExecution方法通知調(diào)用者跟束。具體可以看源碼.
- AsyncTask中的任務(wù)隊(duì)列容量為128
- Android中四種常用的線程池:
-
FixedThreadPool
Executors.newFixedThreadPool()
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
線程數(shù)量固定,當(dāng)線程處于空閑時(shí)丑孩,線程并不會(huì)被回收冀宴,除非線程池關(guān)閉,當(dāng)所有線程處于活動(dòng)狀態(tài)時(shí)温学,新任務(wù)就會(huì)處于等待狀態(tài)略贮,直到有線程空閑下來.
由于FixedThreadPool只有核心線程,并且不會(huì)被??仗岖,所以它會(huì)更加快速的響應(yīng)外界的請求逃延。沒有超時(shí)機(jī)制,任務(wù)隊(duì)列大小也沒閑置轧拄。
-
CachedThreadPool
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
它是一個(gè)線程數(shù)量不固定的線程池揽祥,當(dāng)線程池中的線程都處于活動(dòng)狀態(tài),線程池會(huì)創(chuàng)建新的線程來處理任務(wù)檩电,否者就會(huì)利用空閑的線程來處理新任務(wù)
空閑的線程超過60秒就會(huì)被回收
SynchronousQueue很特殊拄丰,無法存儲元素的隊(duì)列。
該線程池適合大量耗時(shí)較少的任務(wù)俐末,當(dāng)整個(gè)線程池中的線程都處于空閑狀態(tài)時(shí)愈案,線程會(huì)因超時(shí)而被??,這時(shí)它幾乎不占用任何資源
- ScheduledThreadPoolExecutor
public static ScheduledExecutorService newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue(), threadFactory);
}
核心線程數(shù)固定鹅搪,非核心線程數(shù)沒有限制站绪,當(dāng)非核心線程空閑會(huì)被立刻回收
適合執(zhí)行定時(shí)任務(wù)和有固定周期的重復(fù)任務(wù)
參考最后使用示例
- SingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
只有一個(gè)核心線程,所有的任務(wù)都會(huì)放到一個(gè)線程中去順序執(zhí)行
它統(tǒng)一了所有的外界任務(wù)到一個(gè)線程中丽柿,使得這些任務(wù)不需要處理線程間的同步問題恢准。
- 使用示例
Runnable command = new Runnable() {
@Override
public void run() {
SystemClock.sleep(1000);
}
};
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
fixedThreadPool.execute(command);
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
cachedThreadPool.execute(command);
//2000ms后執(zhí)行command
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
scheduledExecutorService.schedule(command, 2000, TimeUnit.MILLISECONDS);
//延遲10ms后執(zhí)行,以后每隔1000ms執(zhí)行一次command
scheduledExecutorService.scheduleAtFixedRate(command, 10, 1000, TimeUnit.MILLISECONDS);
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
singleThreadExecutor.execute(command);