AsyncTask源码简析

(源码来自sdk7.0)
构造方法
构造方法有3个

/**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     */
    public AsyncTask() {
        this((Looper) null);
    }

    /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     *
     * @hide
     */
    public AsyncTask(@Nullable Handler handler) {
        this(handler != null ? handler.getLooper() : null);
    }

    /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     *
     * @hide
     */
    public AsyncTask(@Nullable Looper callbackLooper) {

第3个构造是主要构造,但被隐藏了。应用层常用到的是无参构造即传入一个null至该构造,实际等价于传入MainLooper。

    /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     *
     * @hide
     */
    public AsyncTask(@Nullable Looper callbackLooper) {
        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
            ? getMainHandler()
            : new Handler(callbackLooper);

但是这里的主线程looper和非主线程looper实际上是分开处理的,非主线程需要自己处理不同message的结果的分发,而主线程的源码中完全替你封装好了。

主线程的mHandler初始化getMainHandler

    private static Handler getMainHandler() {
        synchronized (AsyncTask.class) {
            if (sHandler == null) {
                sHandler = new InternalHandler(Looper.getMainLooper());
            }
            return sHandler;
        }
    }

这个InternalHandler就是做了MESSAGE_POST_RESULT和MESSAGE_POST_PROGRESS的主线程回调

因为静态内部类在假泛型中无法获取到泛型类型,而暴露给API的

protected void onProgressUpdate(Progress... values)

protected void onPostExecute(Result result)

显然希望使用到泛型约束。这里不得已用了unchecked屏蔽编译错误。因为每个AsyncTask的只能执行一次,这里的类型安全是没问题的~~~ 就是代码可读性稍差,

    private static class InternalHandler extends Handler {
        public InternalHandler(Looper looper) {
            super(looper);
        }

        @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]); //主线程调用被复写的onCancel或者onPostExecute
                    break;
                case MESSAGE_POST_PROGRESS:
                    result.mTask.onProgressUpdate(result.mData); //主线程调用被复写的onProgressUpdate
                    break;
            }
        }
    }

构造方法中除了创建了handler,更重要的是初始化了FutureTask

        mWorker = new WorkerRunnable<Params, Result>() {  //WorkRunnable其实就是个Callback的实现,静态内部类存放Params规避内存泄漏
            public Result call() throws Exception {
                mTaskInvoked.set(true);  //mTaskInvoked在call第一行用于标识任务已经被执行。在done中调用postResultIfNotInvoked提取判断
                                         //因为done()函数如果在future的cancel时是由调用线程执行的 可能存在线程安全问题
                Result result = null;
                try {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    //noinspection unchecked
                    result = doInBackground(mParams); //子线程执行执行复写的doInBackground任务
                    Binder.flushPendingCommands(); //以下是该静态函数的api注释
/*将当前线程中挂起的所有Binder命令都刷新到内核驱动。
这可以在执行可能阻塞很长时间的操作之前调用,
以确保任何挂起的对象引用已经被释放。
这样可以防止这一耗时过程的持续时间超过对象应有的生命周期。*/
                } catch (Throwable tr) {
                    mCancelled.set(true); //这里也是一个AtomicBoolean 标识cancel
                    throw tr;
                } finally {
                    postResult(result);//mTaskInvoked被设置为true这句代码执行之后,就保证了final中调用postResult
                }
                return result;
            }
        };

        mFuture = new FutureTask<Result>(mWorker) {
            @Override
            protected void done() {
                try {
                    postResultIfNotInvoked(get());//future阻塞get()获取result 并根据抛出的异常处理状态
                } 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);
                }
            }
        }

这里有个小疑问,mTaskInvoked是一个AtomicBoolean,保证多线程的原子性,但是这里并没有调用compareAndSet方法,那么使用原子类的意义在哪里呢? 这里在我的理解里 应该只需要声明volatile boolean mTaskInvoked就可以了,如有高见欢迎讨论。

postResultIfNotInvoked函数的意义,当future没有执行就被cancel后,cancel调用done()函数,获得到get()将是一个空,这时进入!wasTaskInvoked流程 postResult(null)

private void postResultIfNotInvoked(Result result) {
        final boolean wasTaskInvoked = mTaskInvoked.get();
        if (!wasTaskInvoked) {
            postResult(result);
        }
    }

线程调度

异步任务启动的入口

    @MainThread
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }
    @MainThread
    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
            Params... params) {
        if (mStatus != Status.PENDING) { //这段代码保证AsyncTask只能被执行一次
            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; //配置参数给Callback
        exec.execute(mFuture); //全局调度执行器 接管futrue

        return this;
    }
不管我们通常调用的execute(Params... params)

还是提供给我们直接运行一个runnable的

    @MainThread
    public static void execute(Runnable runnable) {
        sDefaultExecutor.execute(runnable);
    }

实际都是使用全局调度执行器sDefaultExecutor进行处理,它的默认实现是一个串行的分发

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

在主线程调用

并且他的实现保证了串行:全局中多个AsyncTask被execute,只会有deque头部那个成为mActive,依序执行

    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() { //offer插入ruunable到deque的尾部
                //代理包装了r 实际执行是由线程池做的 这里只是添加了 调度工作的代理层
                public void run() {
                    try {  //这样try catch 不阻碍异常的抛出 同时又能保证 一个runnable执行完之后 一定执行下一个
                        r.run();
                    } finally {
                        scheduleNext();
                    }
                }
            });
            if (mActive == null) { //塞进队列后检查:如果现在没有执行的runnable 那么开始干活了
                scheduleNext();
            }
        }

        protected synchronized void scheduleNext() { //这个函数执行时机在1、deque从空到有时 与2、sWorkExecutor有runnable执行完毕时调用
            if ((mActive = mTasks.poll()) != null) { //头部取出 开始执行
                THREAD_POOL_EXECUTOR.execute(mActive);
            }
        }
    }

线程池

我们看到了真正消费mTasks中的Runnable的是THREAD_POOL_EXECUTOR.execute(mActive) 

他是一个全局的executor

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

他也是public的 可以直接设置。缺省值为一个核心线程cpu-1、最大线程2倍cpu、非核心线程待活时间10秒、等待工作队列长度128的线程池

超出工作队列的拒绝策略用的是java缺省的抛异常RejectedExecutionException

    public static class AbortPolicy implements RejectedExecutionHandler {
        /**
         * Creates an {@code AbortPolicy}.
         */
        public AbortPolicy() { }

        /**
         * Always throws RejectedExecutionException.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         * @throws RejectedExecutionException always
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }

可以关注一下线程工厂的计数器 用的是原子类AtomicInt的自增

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





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值