android線程小結

線程

線程是操作系統調度的最小單元,在android中,主線程又稱爲UI線程,執行的是與界面渲染等操作,
而工作線程一般承擔耗時多的操作。

Android中線程的實現方式有以下幾種:

1.AsyncTask 線程池
2.IntentService 線程
3.HandlerThread 線程


AsyncTask

android 1.6 前串行
1.6-3.0 並行
3.0後串行,引入excuteOnExecutor可以進行並行操作

實例化與execute都是只能在主線程進行的
1)execute操作會調用onPreExecute操作
2)靜態成員會在加載類時進行初始化,否則同一進程中的AsyncTask都將無法正常工作

工作原理:

asyncTask中有兩個主要的線程池,分別是
THREAD_POOL_EXECUTOR
這個線程池抓喲是跟具體的任務執行相關,其實例是ThreadPoolExecutor
SERIAL_EXECUTOR
充當串行任務排隊的作用,如果是自己調用excuteOnExecutor,則調度方式由自己傳入的線程池決定

mWorker (WorkerRunnable) 用於執行相關的任務
mFuture (FutrueTask) 用於完成結果回調使用,發送相關的信息,告知handler結束
sHandler (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;
        }
    }
}

1.實例化時,會準備好mWorker 和 mFuture,這兩個相當於回調函數

2.調用excute函數會調用到excuteOnExecutor,此時會調用onPreExecute(),並會交給調度的線程池去調度任務,提取到的任務再交給指定的線程池去執行任務,默認採用THREAD_POOL_EXECUTOR,串行線程池,此時傳入了(mFuture),而mFutrue已傳入mWorker的參數,能夠回調mWorker的 call方法

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);
}
};

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);
}
    }
};

3.在call方法中會調用doInBackground方法,此時,其實此方法其實已經在已開闢的線程池中執行了。
4.執行完,通過postResult讓信息發送給sHandler,再回調onPostExecute 完成整個過程。

總之,巧妙使用了線程池的回調runnable,再通過handler,message實現主,工作線程的消息傳遞。
這裏的handler是主線程下的handler,這主要是保證回調能夠直接操縱UI元素。


HandlerThread

是繼承自Thread的類,自動幫我們創建好looper,這樣創建handler就不用手動Looper初始化了
ps:可以理解爲,集合了looper的thread

@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
    synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
    Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}

其調用主要實現如下:

mHandlerThread = new HandlerThread("MyHandler");
mHandlerThread.start();

mHandler = new Handler(mHandlerThread.getLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {

        return false;
}
});

mHandler.post(new Runnable() {
public void run() {
//任務1
        mHandler.sendMessage();
//任務2
}
});

這樣,就能夠直接在run中執行相關任務。
需要注意的是,初始化後該Thread是無限循環的,需要手動終止線程執行,即調用quitSafely或者quit


IntentService

繼承於Service的一個自帶工作線程的Service=。=優先級還是蠻高的呢
其實現主要依靠handlerThread進行的,onCreate中實例化handlerThread,onStart中發送消息,
然後在handlerMessage過程中調用onHandlerIntent,完成工作線程的任務,完成後直接結束=。=
值得注意的是,退出調用的是stopSelf(int startId); 這會檢查是否有新的消息入列,這對於多次派發任務是有幫助的,不至於那麼快結束。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章