Android多线程--AsyncTask分析

简介

AsyncTask是Android中轻量级的异步类,内部使用两个线程池和Handler完成异步任务,并可以更新UI,其中一个线程池作为线程调度使用,控制多个实例以串行的方式运行,另一个线程池用作执行任务,Handler用来回调主线程。

使用方式

抽象类

public abstract class AsyncTask 

其中
Params:任务开始传入的参数,例execute()中的类型,myAsyncTask.execute(“start”);
Progress:调用进程进度的参数onProgressUpdate()
Result:doInBackground返回的参数类型
以上三个泛型参数我们不需要使用的时候,可以使用Void来代替。

例子

public class MyAsyncTask extends AsyncTask<String, Integer, String>{

        // 作用:执行 线程任务前的操作
        @Override
        protected void onPreExecute() {
            tv.setText("loading...");
            // 执行前显示提示
        }

        // 作用:后台任务,执行耗时操作
        @Override
        protected String doInBackground(String... strings) {
            Log.i("zzb", "strings[0] = " + strings[0]);//打印出start
            try {
                int count = 0;
                int length = 1;
                while (count < 99) {

                    count += length;
                    // 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
                    publishProgress(count);
                    // 模拟耗时任务
                    Thread.sleep(50);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            return "finish";
        }

        // 作用:在主线程 显示线程任务执行的进度
        @Override
        protected void onProgressUpdate(Integer... progresses) {

            pBar.setProgress(progresses[0]);
            tv.setText("loading..." + progresses[0] + "%");

        }

        // 作用:接收线程任务执行结果、将执行结果显示到UI组件
        @Override
        protected void onPostExecute(String result) {
            // 执行完毕后,则更新UI
            tv.setText("加载完毕 " + result);
        }

        // 取消回调
        @Override
        protected void onCancelled() {

            tv.setText("cancel");
            pBar.setProgress(0);

        }
    }

按钮控制启动

myAsyncTask.execute("start");

按钮控制停止

myAsyncTask.cancel(true);

方法分析

执行顺序

myAsyncTask.execute("start")  -> onPreExecute() -> doInBackground() -> publishProgress() ->
onProgressUpdate() -> onPostExecute()

execute():手动执行任务,可以传递参数。必须在主线程中执行
onPreExecute():该方法在异步任务工作之前执行,主要用于一些参数或者UI的初始化操作
doInBackground(Params…params):后台任务,执行耗时操作,可以在内部执行publishProgress()
onProgressUpdate(Progress… values):在主线程中显示任务进度
onPostExecute(Result result):主线程,任务执行完成回调
onCancelled():主线程,任务取消回调

源码分析

1. 线程池:任务执行

    //cpu数
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    //核心线程数
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    //最大线程数
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    //非核心线程数闲置时的超时时长
    private static final int KEEP_ALIVE_SECONDS = 30;

    //线程工厂,创建一个thread并返回
    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);

    /**
     * An {@link Executor} that can be used to execute tasks in parallel.
     */
    public static final Executor THREAD_POOL_EXECUTOR;

    //使用以上参数创建的线程池
    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;
    }

其中AtomicInteger(1),表示线程安全的i++自加或自减操作

2.线程池:串行队列,负责把加进来的任务以串行的形式执行

    //创建串行的线程池
    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

    //这两个参数用作handler分发
    private static final int MESSAGE_POST_RESULT = 0x1;
    private static final int MESSAGE_POST_PROGRESS = 0x2;

    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
    //主线程handler
    private static InternalHandler sHandler;

    //实现了Runable接口,要线程要执行的函数体
    private final WorkerRunnable mWorker;
    //实现Runable接口,但是可以有返回值,监听线程的状态
    private final FutureTask mFuture;

    //这个状态标记是asynctask只能执行一次的原因,初始状态为等待
    private volatile Status mStatus = Status.PENDING;

    //标记:是否取消任务
    private final AtomicBoolean mCancelled = new AtomicBoolean();
    //标记:任务开始执行
    private final AtomicBoolean mTaskInvoked = new AtomicBoolean();

    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) {
            //poll()从头取出任务,交给线程池执行
                THREAD_POOL_EXECUTOR.execute(mActive);
            }
        }
    }

这里实现串行的原理,先执行run方法,等run方法执行完成才调用scheduleNext,从队列中取任务。使得mTasks中的所有Runnable对象依次执行。
注意:在android 1.6版本时,改用并行线程池,3.0之后又变回串行。

3.构造函数

public AsyncTask() {
        mWorker = new WorkerRunnable() {
            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;
            }
        };

        //对任务进行监听,任务执行完成或取消都会执行done()       
        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);
                }
            }
        };
    }
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
        Params[] mParams;
    }

对mWorker和mFuture连个变量进行初始化,其中mWorker是WorkerRunnable的实例,而WorkerRunnable实现了Callable接口,而Callable可以理解为有返回值的Runable。
FutureTask实现了 RunnableFuture接口,而RunnableFuture继承Runnable,
Future提供了对Runnable或者Callable任务的执行结果处理,所以可以在线程池中被执行。在FutureTask的Run方法中,实际上被执行的是传入的Callable的call方法,此处也就是指mWork的call方法。而get()方法里面是获取的我们的Result泛型,拿到的是我们mWorker.call的返回值

private void postResultIfNotInvoked(Result result) {
        //在任务启动后,这里为true
        final boolean wasTaskInvoked = mTaskInvoked.get();
        //mWorker初始化时就已经将mTaskInvoked为true
        //当有多个asynctask任务加入队列,此时取消任务,其他任务还没执行时mTaskInvoked.get返回false,就执行以下内容,保证会回调结束方法。
        if (!wasTaskInvoked) {
            postResult(result);
        }
    }

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

mWorker的call和mFuture的done方法都运行在线程池中,doInBackground方法在call中被执行,所以doInBackground方法可以进行一些耗时操作,如网络请求和数据库操作。此时任务完成会使用handler回调主线程。

4.Hadnler

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;
            }
        }
    }
private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        //标记状态
        mStatus = Status.FINISHED;
    }

Handler只处理两种情况,进度任务和完成任务。
其中完成任务分两种情况,正常完成任务则回调onPostExecute,取消任务则回调onCancelled。

5.execute启动

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

这里把sDefaultExecutor串行的线程池传递进去。

@MainThread
    public final AsyncTask executeOnExecutor(Executor exec,
            Params... params) {
            //这里是asynctask只能执行一次的原因
        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;
    }

我们知道这里的exec.execute(mFuture)先是使用了sDefaultExecutor = SERIAL_EXECUTOR这个串行线程池,加入任务队列,接着调用THREAD_POOL_EXECUTOR中的execute()方法开启线程任务,
execute()方法执行的最终结果是将mFuture中的run()方法启动。

6.FutureTask中的run()

public void run() {
        if (state != NEW ||
            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
            return;
        try {
            //获取callable
            Callable c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    //执行call方法
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                //任务执行完成调用set
                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);
        }
    }

前面说过mWorker实现了callable,调用了它的call(),接着就会调用后台任务doInBackground,这样,整个任务就开始执行。

protected void set(V v) {
        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
            outcome = v;
            U.putOrderedInt(this, STATE, NORMAL); // final state
            finishCompletion();
        }
    }
private void finishCompletion() {
        // assert state > COMPLETING;
        /**省略*/

        //最终执行done
        done();

        callable = null;        // to reduce footprint
    }

任务完成最终会执行mFuture的done方法,接着就是上面说的通过handler回调主线程处理任务完成。

7. Cancel取消

public final boolean cancel(boolean mayInterruptIfRunning) {
        mCancelled.set(true);
        return mFuture.cancel(mayInterruptIfRunning);
    }

内部调用mFuture.cancel方法

public boolean cancel(boolean mayInterruptIfRunning) {
        if (!(state == NEW &&
              U.compareAndSwapInt(this, STATE, NEW,
                  mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
            return false;
        try {    // in case call to interrupt throws exception
            if (mayInterruptIfRunning) {
                try {
                    Thread t = runner;
                    if (t != null)
                        t.interrupt();
                } finally { // final state
                    U.putOrderedInt(this, STATE, INTERRUPTED);
                }
            }
        } finally {
            //最终调用这里去执行done
            finishCompletion();
        }
        return true;
    }

执行Thread中断,最后会调用finishCompletion(),内部调用了mFuture的done方法。

你可能感兴趣的:(Android多线程)