国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

AsyncTask 源碼分析

kk_miles / 1651人閱讀

摘要:的用法的聲明如下是一個(gè)抽象類,同時(shí)也是一個(gè)泛型類。多線程問題通過以上分析,涉及到兩個(gè)線程池。是串行線程池,使用隊(duì)列管理任務(wù)對象。是真正執(zhí)行任務(wù)的線程池,若要實(shí)現(xiàn)并行執(zhí)行任務(wù),則可自定義線程池,傳入方法作為線程池對象。

AsyncTask 分析

位置:frameworksasecorejavaandroidosAsyncTask.java

AsyncTask簡介

在Android中,所有的UI更新操作必須要在主線程中進(jìn)行,而耗時(shí)操作(如訪問網(wǎng)絡(luò)、加載圖片、IO操作等)需要在子線程中進(jìn)行,線程間的交互需要借助Android的異步消息處理機(jī)制,也就是Handler。但是為了更方便地讓子線程與主線程交互,更新UI元素,Android系統(tǒng)提供了輕量級的異步任務(wù)類AsyncTask。

AsyncTask的用法

AsyncTask的聲明如下:

public abstract class AsyncTask

AsyncTask是一個(gè)抽象類,同時(shí)也是一個(gè)泛型類。在使用時(shí)需要?jiǎng)?chuàng)建子類去繼承它,并指定相應(yīng)的泛型類型參數(shù)。三個(gè)參數(shù)的含義

Params
執(zhí)行AsyncTask時(shí)需要傳入的參數(shù),用于執(zhí)行后臺(tái)任務(wù)。

Progress
顯示任務(wù)進(jìn)度單位。

Result
任務(wù)執(zhí)行完畢后返回的結(jié)果

一個(gè)簡單的AsyncTask使用示例:

class DownloadTask extends AsyncTask {

    @Override
    protected void onPreExecute() {
        progressDialog.show();
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        try {
            while (true) {
                int downloadPercent = doDownload();
                publishProgress(downloadPercent);
                if (downloadPercent >= 100) {
                    break;
                }
            }
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        progressDialog.setMessage("當(dāng)前下載進(jìn)度:" + values[0] + "%");
    }

    @Override
    protected void onPostExecute(Boolean result) {
        progressDialog.dismiss();
        if (result) {
            Toast.makeText(context, "下載成功", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(context, "下載失敗", Toast.LENGTH_SHORT).show();
        }
    }
}

onPreExecute
此方法會(huì)在后臺(tái)任務(wù)執(zhí)行前被調(diào)用,用于進(jìn)行一些準(zhǔn)備工作,在主線程執(zhí)行。

doInBackground
此方法為要執(zhí)行的后臺(tái)任務(wù),在子線程中執(zhí)行。不能進(jìn)行UI操作。

onProgressUpdate
顯示任務(wù)執(zhí)行進(jìn)度,在doInBackground中調(diào)用publishProgress(Progress... values),values會(huì)傳入此方法中,進(jìn)行進(jìn)度顯示。在主線程執(zhí)行。

onPostExecute
當(dāng)后臺(tái)任務(wù)執(zhí)行完畢后,通過return語句返回執(zhí)行結(jié)果,執(zhí)行結(jié)果傳入此方法作為參數(shù)

任務(wù)的啟動(dòng):

new DownloadTask().execute(); 
AsyncTask源碼分析

基于Android 6.0源碼

首先看AsyncTask的構(gòu)造函數(shù):

public AsyncTask() {
        mWorker = new WorkerRunnable() {
            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(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òu)造函數(shù)里初始化了兩個(gè)對象:mWorker和mFuture,mWorker是WorkerRunnable抽象類,實(shí)現(xiàn)了Callable接口。在mWorker的call()方法中,mTaskInvoked.set(true)表示當(dāng)前任務(wù)已被調(diào)用過,然后設(shè)置當(dāng)前線程的優(yōu)先級。接著調(diào)用AsyncTask的doInBackground(mParams)方法執(zhí)行后臺(tái)任務(wù),并將執(zhí)行結(jié)果存入result傳入postResult方法。因此,要執(zhí)行的后臺(tái)任務(wù)包含在了AsyncTask的mWorker的call()方法中。
然后是mFuture,mFuture是一個(gè)FutureTask類對象,在構(gòu)造方法中傳入mWorker作為參數(shù)。mFuture其實(shí)是一個(gè)封裝了mWorker的FutureTask對象,F(xiàn)utureTask類實(shí)現(xiàn)了FutureRunnable接口,通過這個(gè)接口可以方便的取消后臺(tái)任務(wù)以及獲取后臺(tái)任務(wù)的執(zhí)行結(jié)果,具體可參考:Java并發(fā)編程:Callable、Future和FutureTask。
由上分析可知:后臺(tái)任務(wù)在mWorker的call()方法中,當(dāng)call()被執(zhí)行時(shí)后臺(tái)任務(wù)doInBackground也就會(huì)被執(zhí)行了。那么何時(shí)才會(huì)被執(zhí)行?因?yàn)閙Worker又封裝在了mFuture中,因此當(dāng)mFuture對象被提交到AsyncTask包含的線程池執(zhí)行時(shí),call方法就會(huì)被調(diào)用,自定義的后臺(tái)任務(wù)也就開始執(zhí)行了。

要啟動(dòng)某一個(gè)任務(wù),就需要調(diào)用該任務(wù)的execute()方法,下面看execute()方法的源碼:

public final AsyncTask execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }

在執(zhí)行execute時(shí)傳入params參數(shù),這個(gè)參數(shù)會(huì)一層一層傳遞到doInBackground方法中,方法中調(diào)用了executeOnExecutor并將其返回值返回,傳入了兩個(gè)參數(shù),其中sDefaultExecutor是AsyncTask默認(rèn)的線程池。

下面看executeOnExecutor方法:

public final AsyncTask 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;
    }

在executeOnExecutor方法中,首先判斷任務(wù)的狀態(tài),當(dāng)任務(wù)正在運(yùn)行或已經(jīng)結(jié)束時(shí)會(huì)拋出異常。
然后調(diào)用了AsyncTask的 onPreExecute() 方法,因此前面自定義的AsyncTask類中,onPreExecute()方法會(huì)第一個(gè)被執(zhí)行。
然后將傳入的params賦值給mWorker的mParams變量
然后執(zhí)行exec的execute()方法,傳入mFuture作為參數(shù),exec就是前面?zhèn)鬟M(jìn)來的sDefaultExecutor
接下來看看sDefaultExecutor

    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
    ……
    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

sDefaultExecutor是一個(gè)靜態(tài)的SerialExecutor常量,SerialExecutor類定義如下:

private static class SerialExecutor implements Executor {
        final ArrayDeque mTasks = new ArrayDeque();
        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類是一個(gè)串行線程池,其中定義了一個(gè)mTasks任務(wù)緩存隊(duì)列。
在execute方法中,mTasks.offer向緩存隊(duì)列添加了一個(gè)Runnable任務(wù),任務(wù)中run方法執(zhí)行了r.run(),其實(shí)就是調(diào)用前面?zhèn)魅氲膍Future對象的run方法,而mFuture的run方法內(nèi)部會(huì)調(diào)用mWorker的call方法,然后就會(huì)調(diào)用doInBackground方法,因此后臺(tái)任務(wù)就開始執(zhí)行了。
提交到任務(wù)緩存隊(duì)列中的任務(wù)什么時(shí)候會(huì)被執(zhí)行呢?
SerialExecutor中定義了一個(gè)Runnable對象mActive,表示當(dāng)前正在執(zhí)行的任務(wù),當(dāng)?shù)谝淮螆?zhí)行execute時(shí),mActive肯定是null,因此進(jìn)入if語句執(zhí)行scheduleNext(),取出第一個(gè)任務(wù)賦給mActive并判斷是否為null,然后調(diào)用THREAD_POOL_EXECUTOR.execute()方法傳入mActive參數(shù),執(zhí)行取出的mActive引用的任務(wù)對象。此時(shí)后臺(tái)任務(wù)真正開始。
當(dāng)有新的任務(wù)被執(zhí)行時(shí),同樣會(huì)offer()方法將傳入的Runnable添加到隊(duì)列的尾部,在后續(xù)操作判斷mActive就是非null,則不會(huì)進(jìn)入if語句中。
但是,第一個(gè)任務(wù)被執(zhí)行時(shí),在Runnable的run方法,中finally中調(diào)用了scheduleNext()方法,因此每當(dāng)一個(gè)任務(wù)執(zhí)行完畢后,下一個(gè)任務(wù)才會(huì)得到執(zhí)行,SerialExecutor模仿的是單一線程池的效果,如果啟動(dòng)了很多任務(wù),同一時(shí)刻只會(huì)有一個(gè)線程正在執(zhí)行,其余的均保存在任務(wù)隊(duì)列中,處于等待狀態(tài)。

由上可知,真正執(zhí)行任務(wù)的是THREAD_POOL_EXECUTOR

 public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

THREAD_POOL_EXECUTOR是一個(gè)線程池,它的配置如下:

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE = 1;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
        }
    };

    private static final BlockingQueue sPoolWorkQueue =
            new LinkedBlockingQueue(128);

核心線程數(shù)corePoolSize為CPU數(shù)加一;

最大線程數(shù)maximumPoolSize為CPU數(shù)的二倍加一;

存活時(shí)間為1秒;

任務(wù)緩存隊(duì)列為LinkedBlockingQueue,最多緩存128個(gè)任務(wù)。

前面說了,當(dāng)子線程執(zhí)行任務(wù)時(shí),其實(shí)是執(zhí)行mFuture對象的run方法,也就是執(zhí)行mWorker對象的call()方法
下面再看一下mWorker對象的call()方法:

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

doInBackground的執(zhí)行結(jié)果保存在result,作為參數(shù)傳入postResult()方法
postResult():

private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult(this, result));
        message.sendToTarget();
        return result;
    }

這里通過AsyncTask類內(nèi)部的Handler對象發(fā)出一條MESSAGE_POST_RESULT消息,消息內(nèi)保存了AsyncTaskResult對象,該對象封裝了任務(wù)的執(zhí)行結(jié)果。
下面看一下這個(gè)Handler的相關(guān)源碼:

private static Handler getHandler() {
        synchronized (AsyncTask.class) {
            if (sHandler == null) {
                sHandler = new InternalHandler();
            }
            return sHandler;
        }
    }
    
    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;
            }
        }
    }

在主線程創(chuàng)建一個(gè)sHandler對象

收到MESSAGE_POST_PROGRESS消息后,會(huì)調(diào)用onProgressUpdate方法,MESSAGE_POST_PROGRESS消息通過publishProgress方法發(fā)送,我們常會(huì)在doInBackground方法中調(diào)用這個(gè)方法,用于回傳任務(wù)執(zhí)行進(jìn)度。

protected final void publishProgress(Progress... values) {
        if (!isCancelled()) {
            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                    new AsyncTaskResult(this, values)).sendToTarget();
        }
    }

當(dāng)sHandler收到MESSAGE_POST_RESULT消息后,會(huì)調(diào)用finish方法

private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }

在finish方法中,首先判斷任務(wù)的狀態(tài),然后執(zhí)行onPostExecute方法,最后設(shè)置任務(wù)狀態(tài)為FINISHED,當(dāng)前的AsyncTask任務(wù)全部執(zhí)行完畢。

多線程問題

通過以上分析,AsyncTask涉及到兩個(gè)線程池:SerialExecutor、ThreadPoolExecutor。

SerialExecutor是串行線程池,使用ArrayDeque隊(duì)列管理任務(wù)(Runnable對象)。它同時(shí)只能執(zhí)行一個(gè)任務(wù),多個(gè)任務(wù)要等待上一個(gè)任務(wù)執(zhí)行完畢才能繼續(xù)執(zhí)行下一個(gè)。它在AsyncTask中的作用是保證任務(wù)按順序地一個(gè)接一個(gè)串行執(zhí)行

ThreadPoolExecutor是真正執(zhí)行任務(wù)的線程池,若要實(shí)現(xiàn)并行執(zhí)行任務(wù),則可自定義線程池,傳入executeOnExecutor(Executor exec, Params... params)方法作為線程池對象。如:

Executor exec = new ThreadPoolExecutor(15, 200, 10,  
        TimeUnit.SECONDS, new LinkedBlockingQueue());  
new DownloadTask().executeOnExecutor(exec,params);  

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/67445.html

相關(guān)文章

  • AsyncTask異步任務(wù)類

    摘要:異步任務(wù)的構(gòu)造方法主要用于初始化線程池先關(guān)的成員變量創(chuàng)建一個(gè)新的異步任務(wù)。所以,我們是必須確保在銷毀活動(dòng)之前取消任務(wù)。 目錄介紹 01.先看下AsyncTask用法 02.AsyncTask源碼深入分析 2.1 構(gòu)造方法源碼分析 2.2 看execute(Params... params)方法 2.3 mWorker和mFuture的創(chuàng)建過程 03.異步機(jī)制的實(shí)現(xiàn) 04.不同...

    dongxiawu 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<