Android中的線程相關(guān)

線程的概念在編程中是很重要的,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ù)的。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android中的線程 線程,在Android中是非常重要的,主線程處理UI界面,子線程處理耗時(shí)操作。如果在主線程...
    shenhuniurou閱讀 875評(píng)論 0 3
  • 從用途上來(lái)說(shuō),線程分為主線程和子線程,主線程主要處理和界面相關(guān)的事情,子線程則往往用于執(zhí)行耗時(shí)操作。 除了Thre...
    小柏不是大白閱讀 708評(píng)論 0 3
  • 七絕 沐遲陽(yáng) 文:微女郎 身沐遲陽(yáng)詠夕輝, 鋪絨耀閃任風(fēng)吹。 秋波金水動(dòng)心刻, 天地盡溶忘我誰(shuí)。
    曉霞初陽(yáng)閱讀 243評(píng)論 2 2
  • 你真的了解你內(nèi)在的那個(gè)自己?jiǎn)??你的孤單,榮耀,幸與不幸,所有這些感覺(jué)深層次的原因,你真的了解嗎? 1 這段時(shí)間在學(xué)...
    Jane漂漂閱讀 2,357評(píng)論 28 68
  • 女人的顏值和善良,如果沒(méi)有智商保護(hù),跟豬圈里待宰的豬結(jié)果是一樣的——越出彩死得越快。 自古紅顏多禍水,這話一半是敗...
    助心閱讀 883評(píng)論 0 0

友情鏈接更多精彩內(nèi)容