線程的概念在編程中是很重要的,Android當(dāng)然也不例外了。如果單純以用途來(lái)講的話,線程分為主線程和子線程,一般來(lái)說(shuō),耗時(shí)操作要放在子線程里去做,所以子線程又叫工作線程,與界面有關(guān)的事情要放在主線程里去做,所以主線程又叫UI線程。說(shuō)起線程,大家可能都知道Thread,但是,除了這個(gè)這個(gè)之外,還是有很多可以扮演線程的角色的,比如底層用到線程池和Handler的AsyncTask、底層直接使用傳統(tǒng)線程的IntentService和HandlerThread。今天就來(lái)了解下這三個(gè)吧。
AsyncTask
AsyncTask是一個(gè)底層封裝了線程池和Handler的輕量級(jí)的異步任務(wù)的類。可以在后臺(tái)執(zhí)行耗時(shí)任務(wù),完成后將結(jié)果傳遞給主線程中。極大的方便了線程的操作。但是,既然都說(shuō)了是輕量級(jí)的了,當(dāng)然是有很多限制的了。第一、它不能去執(zhí)行特別耗時(shí)的任務(wù),有人用AsyncTask來(lái)執(zhí)行網(wǎng)絡(luò)請(qǐng)求,其實(shí)這樣是不好的,網(wǎng)絡(luò)請(qǐng)求我覺(jué)的應(yīng)該用線程池比較好的,很多網(wǎng)絡(luò)庫(kù)中也是這么做的。第二、AsyncTask必須在主線程中創(chuàng)建。第三、execute方法必須在UI線程中調(diào)用。第四、AsyncTask對(duì)象只能調(diào)用一次execute方法。為什么呢?最好的答案當(dāng)然在源碼中了。
分析源碼首先要從入口處分析,然后選擇性跳入.
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
繼續(xù)跟蹤
@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;
}
/**
* Convenience version of {@link #execute(Object...)} for use with
* a simple Runnable object. See {@link #execute(Object[])} for more
* information on the order of execution.
*
* @see #execute(Object[])
* @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
*/
@MainThread
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}
那么,這個(gè)sDefaultExecutor又是什么東東呢?它呢?實(shí)際上是一個(gè)串行的線程池,同一個(gè)進(jìn)程中的所有的AsyncTask都會(huì)在這個(gè)池子里排隊(duì)執(zhí)行,并且按發(fā)起任務(wù)的先后來(lái)排隊(duì)。好吧,還是先看代碼吧。
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();
}
}A
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
上面的代碼可以看出它是怎樣排隊(duì)的,execute方法會(huì)把線程任務(wù)插入到mTasks的隊(duì)尾,如果沒(méi)有正在活動(dòng)的AsyncTask,那么就會(huì)調(diào)用scheduleNext方法執(zhí)行下一個(gè)任務(wù),當(dāng)任務(wù)執(zhí)行完的時(shí)候也會(huì)調(diào)用scheduleNext方法執(zhí)行下一個(gè)任務(wù),由此可見(jiàn),AsyncTask不是并行而是串行的。當(dāng)然要想讓它并行也是可以的, 調(diào)用executeOnExecutor方法就行了。其實(shí)我在看源碼的時(shí)候還發(fā)現(xiàn)了AsyncTask內(nèi)部是由兩個(gè)線程池的,順便看下。
/**
* An {@link Executor} that can be used to execute tasks in parallel.
*/
public static final Executor THREAD_POOL_EXECUTOR;
/**
* An {@link Executor} that executes tasks one at a time in serial
* order. This serialization is global to a particular process.
*/
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();```
其實(shí)注釋已經(jīng)寫的很清楚了,前者是真正用來(lái)執(zhí)行任務(wù)的,后者是用來(lái)排序的。
剛才說(shuō)AsyncTask封裝了線程池和Handler,那么Handler呢?別急,我們看看和handler相關(guān)的代碼。
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(result);
}
};
這個(gè)方法位于構(gòu)造方法里,我們看postResult(result),很明顯后臺(tái)任務(wù)執(zhí)行外后,要通過(guò)這個(gè)方法傳遞結(jié)果到主線程的,很容易想到與Handler有關(guān)系的。那么繼續(xù)跟蹤,
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
果然,這里見(jiàn)到了熟悉的代碼,那么從哪里接受到的呢?Ctrl+F "MESSAGE_POST_RESULT"是很容易找到的。
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;
}
}
}
可以看到這是一個(gè)static的Handler,為了可以切換到主線程,要求InternalHandler對(duì)象要在主線程實(shí)例化,所以AsyncTask也要在主線程中創(chuàng)建。
#### HandlerThread
HandlerThread繼承Thread 是一個(gè)特殊的Thread,可以實(shí)現(xiàn)Handler的Thread
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
上面的代碼中可以看出,HandlerThread在其run方法里創(chuàng)建了一個(gè)消息隊(duì)列,然后 Looper.loop(),開啟消息循環(huán)。需要注意的是,這里 Looper.loop()開啟的是一個(gè)無(wú)限的循環(huán),因此,用完后記得終止線程,具體可以通過(guò)quit或者quitSafely ,quitSafely相比于quit方法安全之處在于清空消息之前會(huì)派發(fā)所有的非延遲消息。
#### IntentService
IntentService是一個(gè)特殊的Service,和Service一樣,要想使用它必須創(chuàng)建它的子類。它可以執(zhí)行后臺(tái)耗時(shí)任務(wù),而且優(yōu)先級(jí)較高,不容易被殺死。它封裝了HandlerThread和Handler
@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時(shí)都會(huì)調(diào)用onStart方法像mServiceHandler發(fā)送一個(gè)消息,消息會(huì)在HandlerThread中被處理。mServiceHandler收到消息最終會(huì)交給onHandleIntent處理。onHandleIntent執(zhí)行結(jié)束后,IntentService會(huì)通過(guò)stopSelf(msg.arg1)來(lái)停止服務(wù),這個(gè)方法會(huì)等待所有的消息都處理完才來(lái)終止服務(wù)。每執(zhí)行一個(gè)任務(wù)就需要啟動(dòng)一次IntentService,IntentService內(nèi)部是通過(guò)消息機(jī)制像HandlerThread請(qǐng)求執(zhí)行任務(wù)的,而Handler中的Looper是順序處理消息的,這意味著IntentService也是順序執(zhí)行后臺(tái)任務(wù)的。