AsyncTask的使用及其原理

2019-08-12  本文已影响0人  pisfans

概述

Android 已封装好的轻量级异步类。内置一个线程池用于异步任务,另一个线程池用于排队(实际不是线程池)。一个默认绑定mainLooper的Handler用于UI线程。

使用

源码分析

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

THREAD_POOL_EXECUTOR 是真正用于异步任务的线程池。可以看到它是静态的,也就是每次new AsyncTask()都是用的同一个线程池。

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static class SerialExecutor implements Executor {
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();//ArrayDeque依赖于可变数组来实现的双端队列,可根据需求自动进行扩容。
        Runnable mActive;//当前执行的任务

        public synchronized void execute(final Runnable r) {
            mTasks.offer(new Runnable() {//offer向队列中插入一个元素,并返回true,如果队列已满,返回false(add在满时报错)
                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);
            }
        }
    }

SERIAL_EXECUTOR 是实现了Executor 接口,但内部操作是把Runnable 任务放入一个ArrayDeque(双端队列)。并且每执行完一个取出下一个任务执行。其实它不是线程池。
AsyncTask.execute()默认会调用到这个对象执行,它会一个个的取出任务再用真正的线程池THREAD_POOL_EXECUTOR执行,由此可见,用一个AsyncTask对象执行多个任务会是串行执行的。那么如何让它并行执行呢?改为调用AsyncTask.executeOnExecuter(AsyncTask.THREAD_POOL_EXECUTOR,"")就可以了。

 public AsyncTask(@Nullable Looper callbackLooper) {// 默认构造方法会走到这里
        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
            ? getMainHandler()// 一般是绑定mainLooper的内置的Handler类
            : new Handler(callbackLooper);// 特殊情况

        mWorker = new WorkerRunnable<Params, Result>() { // 继承callable的类
            public Result call() throws Exception {
                mTaskInvoked.set(true);// 调用标识,FutureTask的done方法里调postResultIfNotInvoked会判断
                Result result = null;
                try {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);// 设置线程的优先级
                    //noinspection unchecked
                    result = doInBackground(mParams);//这里调关键方法doInBackground,执行耗时任务,并获取结果
                    Binder.flushPendingCommands(); //将进程中未执行的命令,一并送往CPU处理
                } catch (Throwable tr) {
                    mCancelled.set(true);//如果运行异常,设置取消的标志
                    throw tr;
                } finally {
                    postResult(result);//发送结果
                }
                return result;
            }
        };
        //一个包装任务的包装类,与callable结合使用
        mFuture = new FutureTask<Result>(mWorker) {
            @Override
            protected void done() {
                try {//在执行完任务做一道检查,将没被调用的Result也一并发出.这个方法根据上面的mTaskInvoked判断
                    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);//如果发生异常,则将结果滞null发出.
                }
            }
        };
    }

callable与runnable的区别是,他的call方法有返回值。所以AsyncTask没有用runnable而是用的

上一篇下一篇

猜你喜欢

热点阅读