Android中的線程
線程,在Android中是非常重要的,主線程處理UI界面,子線程處理耗時(shí)操作。如果在主線程中處理耗時(shí)操作就會(huì)發(fā)生ANR,這對(duì)一個(gè)程序來說是非常致命的,因此耗時(shí)操作必須放在子線程中去執(zhí)行。
在Android系統(tǒng)中,除了Thread外,還有很多AsyncTask、IntentService可以扮演線程角色,另外,HandlerThread也是一種特殊的的線程,盡管它們的表現(xiàn)形式不同于傳統(tǒng)線程Thread,但它們的本質(zhì)依然是傳統(tǒng)的線程。AsyncTask的底層用到了線程池,IntentService和HandlerThread底層則是直接使用了線程。
AsyncTask封裝了線程池和Handler,它主要是為了方便開發(fā)者在子線程中更新UI,實(shí)際上還是通過Handler將更新UI的操作從子線程切換到主線程來的。HandlerThread是一種具有消息循環(huán)的線程,在它的內(nèi)部可以使用Handler。IntentService是一個(gè)服務(wù),系統(tǒng)對(duì)其進(jìn)行了封裝,使其可以更方便的執(zhí)行后臺(tái)任務(wù), IntentService內(nèi)部采用HandlerThread來執(zhí)行任務(wù),當(dāng)任務(wù)執(zhí)行完后IntentService會(huì)自動(dòng)退出。從任務(wù)執(zhí)行的角度看,IntentService的作用像是一個(gè)后臺(tái)線程,但I(xiàn)ntentService是一種服務(wù),它不容易被系統(tǒng)殺死從而可以盡量保證任務(wù)的執(zhí)行,而如果是一個(gè)后臺(tái)線程,由于這個(gè)時(shí)候進(jìn)程中沒有活動(dòng)的四大組件,那么這個(gè)進(jìn)程的優(yōu)先級(jí)就會(huì)非常低,會(huì)很容易被系統(tǒng)殺死,這就是IntentService的優(yōu)點(diǎn)。
線程的創(chuàng)建和銷毀都需要開銷,在系統(tǒng)中我們不能頻繁的創(chuàng)建線程,如果我們需要大量的線程時(shí),正確的做法是采用線程池,一個(gè)線程池中會(huì)緩存一定數(shù)量的線程,通過線程池就可以避免因?yàn)轭l繁創(chuàng)建和銷毀線程所帶來的系統(tǒng)開銷。
主線程和子線程
主線程是指進(jìn)程所擁有的線程,默認(rèn)一個(gè)進(jìn)程只有一個(gè)線程,就是主線程,主線程主要處理界面交互相關(guān)的邏輯,因?yàn)橛脩綦S時(shí)會(huì)和UI界面發(fā)生交互,所以主線程必須在任何時(shí)候都有較高的響應(yīng)速度,否則就會(huì)產(chǎn)生界面卡頓現(xiàn)象。要保持高響應(yīng)速度,就要求在主線程中不能執(zhí)行耗時(shí)任務(wù),這時(shí)子線程就出場(chǎng)了。除了主線程以外的線程都叫子線程。
Android沿用了Java的線程模型,從Android3.0開始系統(tǒng)要求網(wǎng)絡(luò)訪問必須在子線程中進(jìn)行,否則會(huì)訪問失敗,并拋出NetworkOnMainThreadException,這樣做是為了避免主線程由于被耗時(shí)操作阻塞從而出現(xiàn)ANR現(xiàn)象。
AsyncTask
AsyncTask是一種輕量級(jí)的異步任務(wù)類,它可以在線程池中執(zhí)行后臺(tái)任務(wù),然后把執(zhí)行的進(jìn)度和最終結(jié)果傳遞給主線程并在主線程中更新UI。AsyncTask封裝了ThreadPool和Handler,通過AsyncTask可以更方便地執(zhí)行后臺(tái)任務(wù)以及在主線程中訪問UI。
AsyncTask是一個(gè)抽象的泛型類,它提供了Params、Progress和Result這三個(gè)泛型參數(shù),其中Params表示參數(shù)類型,Progress表示后臺(tái)任務(wù)執(zhí)行進(jìn)度的類型,Result表示后臺(tái)任務(wù)返回的結(jié)果類型。如果AsyncTask不需要傳遞具體的參數(shù),那么這三個(gè)泛型參數(shù)可以用Void代替。
class MainAsyncTask extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Void doInBackground(Void... params) {
return null;
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
@Override
protected void onCancelled() {
super.onCancelled();
}
}
基本上我們常用的方法就是上面這幾個(gè)了。
onPreExecute 在主線程中執(zhí)行,在異步任務(wù)執(zhí)行之前,此方法被調(diào)用,一般可以做一些準(zhǔn)備工作。
doInBackground 在線程池中執(zhí)行,此方法用于執(zhí)行異步任務(wù),在此方法中可以通過publishProgress方法來更新任務(wù)的執(zhí)行進(jìn)度,publishProgress方法會(huì)調(diào)用onProgressUpdate方法。另外此方法返回任務(wù)的執(zhí)行結(jié)果給onPostExecute方法。
onProgressUpdate 在主線程中執(zhí)行,當(dāng)后臺(tái)任務(wù)的執(zhí)行進(jìn)度發(fā)生改變時(shí)此方法會(huì)被調(diào)用。
onPostExecute 在主線程中執(zhí)行,當(dāng)異步任務(wù)執(zhí)行完后此方法會(huì)被調(diào)用,它的參數(shù)是后臺(tái)任務(wù)doInBackground的返回值。
onCancelled 在主線程中執(zhí)行,當(dāng)異步任務(wù)被取消時(shí),此方法被調(diào)用,此時(shí)onPostExecute方法將不會(huì)再被調(diào)用。
AsyncTask在具體使用過程中,也有一些條件限制:
AsyncTask的類必須在主線程中加載,也就是第一次訪問AsyncTask必須是在主線程,在Android4.1及以上版本已被系統(tǒng)自動(dòng)完成。
AsyncTask的對(duì)象必須在主線程中創(chuàng)建。
execute方法必須在主線程中調(diào)用。
不能在程序中直接調(diào)用onPreExecute、onPostExecute、doInBackground和onProgressUpdate方法。
一個(gè)AsyncTask對(duì)象只能執(zhí)行一次,也就是只能調(diào)用一次execute方法,否則會(huì)報(bào)運(yùn)行時(shí)異常。
在Android1.6之前,AsyncTask是串行執(zhí)行任務(wù)的,Android1.6的時(shí)候AsyncTask開始采用線程池來處理并行任務(wù),但是從Android3.0開始,為了避免AsyncTask帶來的并發(fā)錯(cuò)誤,AsyncTask又采用一個(gè)線程來串行執(zhí)行任務(wù)。但是在Android3.0及以后的版本中,我們?nèi)匀豢梢酝ㄟ^AsyncTask的executeOnExecutor方法來并行執(zhí)行任務(wù)。
AsyncTask的工作原理
首先我們從它的execute方法開始分析,代碼如下:
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
看源碼可以發(fā)現(xiàn),executeOnExecutor方法的第一個(gè)參數(shù)sDefaultExecutor其實(shí)是一個(gè)串行的線程池,一個(gè)進(jìn)程中所有的AsyncTask全都在這個(gè)串行的線程池中排隊(duì)執(zhí)行,executeOnExecutor方法中AsyncTask的onPreExecute方法最先執(zhí)行,然后線程池開始執(zhí)行。上面的exec其實(shí)就是sDefaultExecutor。
線程池的執(zhí)行過程:
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
private static InternalHandler sHandler;
private final WorkerRunnable<Params, Result> mWorker;
private final FutureTask<Result> mFuture;
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
從SerialExecutor的實(shí)現(xiàn)可以分析AsyncTask的排隊(duì)執(zhí)行過程。首先系統(tǒng)會(huì)把AsyncTask的Params參數(shù)封裝為FutureTask對(duì)象,F(xiàn)utureTask是一個(gè)并發(fā)類,相當(dāng)于Runnable,然后把這個(gè)FutureTask傳遞給SerialExecutor的execute方法去處理,execute方法則是把FutureTask對(duì)象插入到任務(wù)隊(duì)列mTasks中,上面的offer方法就是把這個(gè)對(duì)象添加到隊(duì)列的最后面。如果這時(shí)沒有正在活動(dòng)的AsyncTask任務(wù),就會(huì)調(diào)用scheduleNext方法來執(zhí)行下一個(gè)AsyncTask任務(wù)。當(dāng)一個(gè)AsyncTask任務(wù)執(zhí)行完后會(huì)繼續(xù)執(zhí)行其它任務(wù)直到所有的任務(wù)都被執(zhí)行為止,這么看來,AsyncTask默認(rèn)是串行執(zhí)行的。
依然是上面的代碼,我們發(fā)現(xiàn)AsyncTask內(nèi)部有兩個(gè)線程池:SerialExecutor和THREAD_POOL_EXECUTOR,一個(gè)Handler:InternalHandler,其中SerialExecutor用于任務(wù)的排隊(duì),THREAD_POOL_EXECUTOR用于真正執(zhí)行任務(wù),因?yàn)樵诜椒╯cheduleNext中就是使用THREAD_POOL_EXECUTOR.execute方法來執(zhí)行任務(wù)的,InternalHandler則是用于將執(zhí)行環(huán)境從線程池切換到主線程。
AsyncTask的構(gòu)造方法:
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
這個(gè)WorkerRunnable的call方法什么時(shí)候被調(diào)用?還記得線程池剛執(zhí)行時(shí)傳遞了一個(gè)參數(shù)mFuture嗎?這個(gè)mFuture就是AsyncTask構(gòu)造方法中的這個(gè)mFuture,之前我們說過,它是一個(gè)FutureTask對(duì)象,創(chuàng)建這個(gè)FutureTask對(duì)象時(shí),我們將這個(gè)mWorker傳給了它,F(xiàn)utureTask對(duì)象在等待執(zhí)行的列隊(duì)中最后被執(zhí)行時(shí)會(huì)調(diào)用其run方法,我們?cè)倏纯碏utureTask的run方法:
public void run() {
if (state != NEW ||
!U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
可以看到在run方法中有調(diào)用c.call(),這個(gè)c就是FutureTask中的全局變量callable,我們先找這個(gè)callable:
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
看,在FutureTask的構(gòu)造方法中,結(jié)合我們上面所說,這個(gè)callable就是AsyncTask構(gòu)造方法中的mWorker。
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
也就是說mWorker的call方法最終也會(huì)在線程池中執(zhí)行。在該方法中,首先將mTaskInvoked設(shè)為true,表示當(dāng)前任務(wù)已經(jīng)被調(diào)用過了,然后再執(zhí)行AsyncTask的doInBackground方法,接著將其返回值傳遞給postResult方法。
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
postResult方法會(huì)通過InternalHandler對(duì)象發(fā)送一個(gè)MESSAGE_POST_RESULT消息,InternalHandler類定義如下:
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
由于InternalHandler是一個(gè)靜態(tài)類,為了能將執(zhí)行環(huán)境切換到主線程,這就要求InternalHandler必須在主線程中創(chuàng)建(原理在‘Android的消息機(jī)制’中說過),由于靜態(tài)成員會(huì)在加載類的時(shí)候進(jìn)行初始化,因此這就變相要求AsyncTask的類必須在主線程中加載。接著上面的,發(fā)送MESSAGE_POST_RESULT后,調(diào)用了AsyncTask的finish方法:
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
上面這段代碼就很容易理解了,如果AsyncTask被取消了,就調(diào)用onCancelled方法,否則調(diào)用onPostExecute方法,并設(shè)置狀態(tài)為結(jié)束狀態(tài),而且doInBackground方法的返回值也被傳給了onPostExecute方法。
到這AsyncTask的工作過程就分析完了。
Android3.0及以上版本默認(rèn)是串行執(zhí)行的,但是也可以并行執(zhí)行,采用AsyncTask的executeOnExecutor方法,但是這個(gè)方法是從Android3.0新添加的方法,不能在低版本上使用。
HandlerThread
HandlerThread繼承了Thread,它是一種具有消息循環(huán)可以使用Handler的Thread,它的實(shí)現(xiàn)很簡(jiǎn)單,就是在run方法中通過Looper.prepare()來創(chuàng)建消息隊(duì)列,并通過Looper.loop()來開啟消息循環(huán),這樣在實(shí)際使用中就允許在HandlerThread中創(chuàng)建Handler了。run方法如下:
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
從run方法我們可以發(fā)現(xiàn)HandlerThread和普通的Thread有很大區(qū)別,普通的Thread主要用于在run方法中執(zhí)行一個(gè)耗時(shí)任務(wù),而HandlerThread在內(nèi)部創(chuàng)建了消息隊(duì)列,外界需要通過Handler的消息方式來通知HandlerThread執(zhí)行一個(gè)具體的任務(wù)。由于HandlerThread的run方法是一個(gè)無限循環(huán),所以當(dāng)明確不需要再使用HandlerThread時(shí),我們可以通過它的quit或者quitSafely方法來終止線程的執(zhí)行。
IntentService
IntentService是一種特殊的Service,它繼承了Service并且它是一個(gè)抽象類,因此必須創(chuàng)建它的子類才能使用IntentService。IntentService可用于執(zhí)行后臺(tái)耗時(shí)的任務(wù),當(dāng)任務(wù)執(zhí)行完畢后它會(huì)自動(dòng)停止,同時(shí)因?yàn)樗荢ervice,這導(dǎo)致它的優(yōu)先級(jí)比單純的要高很多,所以它不容易被系統(tǒng)殺死。
IntentService的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);
}
當(dāng)IntentService第一次被啟動(dòng)時(shí),會(huì)創(chuàng)建一個(gè)HandlerThread,然后使用它的Looper來構(gòu)造一個(gè)Handler對(duì)象mServiceHandler,這樣,通過mServiceHandler發(fā)送的消息最終都會(huì)在HandlerThread中執(zhí)行,這樣看來,IntentService也適合用于執(zhí)行后臺(tái)任務(wù)。
跟Service一樣,每次啟動(dòng),IntentService都會(huì)調(diào)用onStartCommand方法:
/**
* You should not override this method for your IntentService. Instead,
* override {@link #onHandleIntent}, which the system calls when the IntentService
* receives a start request.
* @see android.app.Service#onStartCommand
*/
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
我們看官方給我們解釋的內(nèi)容:不應(yīng)該重寫onStartCommand這個(gè)方法,而是重寫onHandleIntent方法,因?yàn)槊看蜪ntentservice接收到啟動(dòng)請(qǐng)求時(shí)都會(huì)調(diào)用onHandleIntent方法。在onStartCommand方法中每次都會(huì)調(diào)用onSatrt方法
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
也就是每次啟動(dòng)就發(fā)送一條消息(包含了后臺(tái)任務(wù)的Intent)到HanderThead去處理,而ServiceHandler收到消息后會(huì)將Intent傳遞給onHandleIntent方法去處理。
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
這個(gè)Intent對(duì)象的內(nèi)容和外界的startService(intent)中的intent的內(nèi)容是完全一致的,通過這個(gè)Intent對(duì)象就可以解析出外界啟動(dòng)IntentService時(shí)所傳遞的參數(shù),然后根據(jù)參數(shù)區(qū)分具體的后臺(tái)任務(wù)。
當(dāng)onHandleIntent方法執(zhí)行完后,IntentService就會(huì)通過stopSelf(int startId)方法來嘗試停止服務(wù),為什么說是嘗試呢?這就是stopSelf方法和stopSelf(int startId)方法的區(qū)別,stopSelf方法會(huì)立即停止服務(wù),而這個(gè)時(shí)候可能還有其他消息未處理完,stopSelf(int startId)方法則會(huì)等到所有消息處理完后才停止服務(wù)。stopSelf(int startId)在嘗試停止服務(wù)之前會(huì)判斷最近啟動(dòng)服務(wù)的次數(shù)是否和startId相等,相等就立即停止服務(wù),否則就不停止。
另外,由于每執(zhí)行一個(gè)后臺(tái)任務(wù)就啟動(dòng)一次IntentService,而IntentService內(nèi)部則是通過消息的方式向HandlerThread請(qǐng)求執(zhí)行任務(wù),Handler中的Looper是順序處理消息的,所以IntentService也是順序執(zhí)行后臺(tái)任務(wù)的,當(dāng)有多個(gè)后臺(tái)任務(wù)時(shí),這些任務(wù)也會(huì)按照外界發(fā)起的順序依次執(zhí)行。執(zhí)行完最后一個(gè)時(shí)IntentService停止。
Android中的線程池
使用線程池的好處:
重用線程池中的線程,避免因?yàn)榫€程的創(chuàng)建和銷毀所帶來的性能開銷
能有效控制線程池的最大并發(fā)數(shù),避免大量的線程之間因?yàn)榛ハ鄵屨枷到y(tǒng)資源而導(dǎo)致阻塞現(xiàn)象
能夠?qū)€程進(jìn)行簡(jiǎn)單管理,并提供定時(shí)執(zhí)行以及指定間隔循環(huán)執(zhí)行等功能
ThreadPoolExecutor
ThreadPoolExecutor是線程池的真正實(shí)現(xiàn),它的構(gòu)造方法提供一系列參數(shù)來配置線程池,各個(gè)參數(shù)的含義:
corePoolSize:線程池的核心線程數(shù),默認(rèn)情況下,核心線程會(huì)在線程池中一直存活,即使它們處于閑置狀態(tài),如果將ThreadPoolExecutor的allowCoreThreadTimeOut屬性設(shè)置為true,那么閑置的核心線程在等待新任務(wù)到來時(shí)會(huì)有超時(shí)策略,這個(gè)時(shí)間間隔由keepAliveTime指定,當(dāng)?shù)却龝r(shí)間超過keepAliveTime指定的時(shí)長(zhǎng)后,核心線程就會(huì)被終止。
maximumPoolSize:線程池所能容納的最大線程數(shù),當(dāng)活動(dòng)線程數(shù)達(dá)到這個(gè)數(shù)值后,后續(xù)的新任務(wù)將會(huì)被阻塞。
keepAliveTime:非核心線程閑置時(shí)的超時(shí)時(shí)長(zhǎng),超過這個(gè)時(shí)長(zhǎng),非核心線程就會(huì)被回收,當(dāng)allowCoreThreadTimeOut設(shè)置為true時(shí),keepAliveTime同樣會(huì)作用于核心線程。
unit:用于指定keepAliveTime參數(shù)的時(shí)間單位,這是一個(gè)枚舉,常用的有TimeUnit.MILLISECONDS、TimeUnit.SECONDS、TimeUnit.MINUTES。
workQueue:線程池中的任務(wù)隊(duì)列,通過線程池的execute方法提交的Runnable對(duì)象會(huì)存儲(chǔ)在這個(gè)參數(shù)中。
threadFactory:線程工廠,為線程池提供創(chuàng)建新線程的功能。ThreadFactory是一個(gè)接口,它只有一個(gè)方法:newThread(Runnable r)
RejectedExecutionHandler handler:這個(gè)參數(shù)不常用,當(dāng)線程池?zé)o法執(zhí)行新任務(wù)時(shí),可能是由于任務(wù)隊(duì)列已滿或者是無法成功執(zhí)行任務(wù),這時(shí),ThreadPoolExecutor會(huì)調(diào)用handler的rejectedExecution方法來通知調(diào)用者,默認(rèn)情況下,rejectedExecution方法會(huì)直接拋出一個(gè)RejectedExecutionException,ThreadPoolExecutor為RejectedExecutionHandler提供了幾個(gè)可選值,CallerRunsPolicy、AbortPolicy、DiscardPolicy、DiscardOldestPolicy,它們都是RejectedExecutionHandler的實(shí)現(xiàn)類,其中AbortPolicy是默認(rèn)值。
ThreadPoolExecutor執(zhí)行任務(wù)時(shí)遵循下列規(guī)則:
如果線程池中的線程數(shù)量未達(dá)到核心線程的數(shù)量,那么會(huì)直接啟動(dòng)一個(gè)核心線程來執(zhí)行任務(wù)。
如果線程池中的線程數(shù)量已達(dá)到或超過核心線程的數(shù)量,那么任務(wù)會(huì)被插入到任務(wù)隊(duì)列中排隊(duì)等待執(zhí)行。
如果在上面這條中無法將任務(wù)插入到任務(wù)隊(duì)列中,一般是因?yàn)槿蝿?wù)隊(duì)列已滿,這時(shí)如果線程數(shù)量未達(dá)到線程池規(guī)定的最大值,那么會(huì)會(huì)立刻啟動(dòng)一個(gè)非核心線程來執(zhí)行任務(wù)。
如果上面這條種線程數(shù)量已經(jīng)達(dá)到線程池規(guī)定的最大值,那么久拒絕執(zhí)行此任務(wù),ThreadPoolExecutor就會(huì)調(diào)用RejectedExecutionHandler的rejectedExecution方法來通知調(diào)用者。
下面這是AsyncTask的線程池配置:
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
規(guī)則基本是這樣,以后我們自定義線程池也可以參照這樣:
核心線程數(shù) = CPU核心數(shù) + 1
線程池最大線程數(shù) = CPU核心數(shù) * 2 + 1
核心線程無超時(shí)機(jī)制,非核心線程在閑置時(shí)的超時(shí)時(shí)間 = 1s
任務(wù)隊(duì)列容量 = 128
線程池分類
Android中常見的四種線程池:
FixedThreadPool:是一種線程數(shù)量固定的線程池,當(dāng)線程處于空閑狀態(tài)時(shí)不會(huì)被回收,除非線程池被關(guān)閉。當(dāng)所有的線程都處于活動(dòng)狀態(tài)時(shí)新任務(wù)會(huì)處于等待狀態(tài),直到有線程空閑出來。由于FixedThreadPool只有核心線程,并且這些核心線程不會(huì)被回收,所以它能夠更快速的響應(yīng)外界的請(qǐng)求。它的任務(wù)隊(duì)列也沒有大小限制。
CachedThreadPool:是一種線程數(shù)量不定的線程池,它只有非核心線程,并且最大線程數(shù)為Integer.MAX_VALUE,這種線程池中的空閑線程都有超時(shí)機(jī)制,時(shí)長(zhǎng)為60s。和FixedThreadPool不同的是,CachedThreadPool的任務(wù)隊(duì)列其實(shí)相當(dāng)于一個(gè)空集合,無法存儲(chǔ)任務(wù),所以任何任務(wù)都會(huì)立即被執(zhí)行。這個(gè)特性決定了CachedThreadPool適合執(zhí)行大量的耗時(shí)較少的任務(wù),當(dāng)整個(gè)線程池都處于閑置狀態(tài)時(shí),線程池中的線程都會(huì)超時(shí)而被停止,此時(shí),CachedThreadPool中實(shí)際是沒有任何線程的,幾乎不占任何系統(tǒng)資源。
ScheduledThreadPool:它的核心線程數(shù)是固定的,非核心線程數(shù)沒有限制,并且當(dāng)非核心線程閑置時(shí)會(huì)被立刻回收。這類線程池主要用于執(zhí)行定時(shí)任務(wù)和具有固定周期的重復(fù)任務(wù)。
SingleThreadPool:它只有一個(gè)核心線程,它確保所有的任務(wù)都在同一個(gè)線程中按順序執(zhí)行,SingleThreadPool的意義在于統(tǒng)一所有的外界任務(wù)到一個(gè)線程中,使得在這些任務(wù)之間不需要處理線程同步的問題。
這四種線程池的創(chuàng)建方式:

除了系統(tǒng)這四種線程池,還可以根據(jù)實(shí)際需要靈活地配置線程池。