Android AsyncTask源码

作者: 菜头中 | 来源:发表于2017-06-18 22:43 被阅读0次

    面试常考题

    1.AsyncTask作用是啥?AsyncTask缺点是啥?
    AsyncTask 是一个Thead+Handler类,主要用于异步任务的工作,他由一个串行线程池和一个并行线程池构成,他的缺点是最多有128个任务,超过的话被抛异常拒绝。

    然而只懂这些是不够的 这里写图片描述

    先抛出几个问题?
    1.串行池是怎么工作的?
    2.他是doInBackground的封装到线程run方法,亦或者如何实现线程之间的切换的?
    3.AsyncTask灵活的参数设置是怎么做到的?
    4.为什么AsyncTask只能用来执行一次
    5.如果我想换别的碧池怎么办?
    哔哩哔哩,接下来一点点告诉你(装B中。。。。。。)

    AsyncTask线程池

    正如上面的,AsyncTask有两个池,然而串行池是基于并行池的。先来看看并行池

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

    总得来说就是在静态代码块里面创建一个并行池,
    那么串行池是怎么实现的呢?

    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() {
                    public void run() {//对线程进行再一次包装,为的就是在线程执行完执行SchduleNext
                        try {
                            r.run();
                        } finally {
                            scheduleNext();
                        }
                    }
                });
                if (mActive == null) {//第一次为null就执行
                    scheduleNext();
                }
            }
    
            protected synchronized void scheduleNext() {
                if ((mActive = mTasks.poll()) != null) {
                    THREAD_POOL_EXECUTOR.execute(mActive);
                }
            }
        }
    

    串行池是在并行池基础上封装,为了达到在原有方法上加上scheduleNext基础上,创建一个线程,将原有线程run方法提取出来,mActive在第一次才为空,之后就环环相扣,通过scheduleNext连起来,好神奇


    这里写图片描述

    AsyncTask常用方法工作原理

    public final AsyncTask<Params, Progress, Result> execute(Params... params) 
    //以下是经常需要重写的方法
        protected abstract Result doInBackground(Params... params);
        protected void onPreExecute();//执行前的工作,工作线程
        protected void onPostExecute(Result result)//执行后后的工作,ui线程
        protected void onProgressUpdate(Progress... values)//更新进度,ui线程
    

    首先从execute执行,开始

    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
    //默认线程池指的就是串行线程池
            return executeOnExecutor(sDefaultExecutor, params);
        }
    
     public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
                Params... params) {
            if (mStatus != Status.PENDING) {
                switch (mStatus) {
                    //这就是不能执行多次原因,状态只能pending,running,finished过度,不能返回
                    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;//将传进来参数mWorker,后面细讲
            exec.execute(mFuture);//线程池执行任务,默认是让串行线程池执行任务
    
            return this;
        }
    

    mWork是什么的呢?

    private final WorkerRunnable<Params, Result> mWorker;
    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
            Params[] mParams;//说白了就是来放参数的,并集成callable的
        }
    

    他是在哪里初始化的呢??????????????继续跟踪,发现AsyncTask构造方法
    这里就是封装精妙之处,猴猴看

     public AsyncTask() {
            mWorker = new WorkerRunnable<Params, Result>() {
                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;
                }
            };
    //再用futureTask将mWorker封装起来
            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);
                    }
                }
            };
        }
    

    最后看看所有执行完后就postResult(result),方法如下

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

    很显然。。。就是转回主线程。

    实现串并行任务混用

    呃呃呃,就是说如何做到先并行执行AB,然后执行c,然后执行CD,画了个xmind画了脑图,不太完整。先上,突然发现存档不见了gg,后续补充。。。。

    相关文章

      网友评论

        本文标题:Android AsyncTask源码

        本文链接:https://www.haomeiwen.com/subject/ysmwqxtx.html