美文网首页
06.源码阅读(AsyncTask深度分析-api26)

06.源码阅读(AsyncTask深度分析-api26)

作者: 任振铭 | 来源:发表于2018-03-29 18:19 被阅读3次

    AsyncTask作为android原生的处理异步任务的方案,问题很多,比如不允许多个任务同时运行,关于这一点,网上有很多说法,早期的说法是AsyncTask最初被引入的时候只支持一个任务同时运行,后期增加到了5个,我今天特意验证了一下看看:

    private void start(View view){
            for (int i = 0; i < 100; i++) {
                new Task().execute();
            }
        }
    
        class Task extends AsyncTask<Void,Void,Void>{
    
            @Override
            protected Void doInBackground(Void... voids) {
                try {
                    int times = 100;
                    for (int i = 0; i < times; i++) {
                        System.out.println("thread"+Thread.currentThread()+i+"");
                        Thread.sleep(10);
                    }
                } catch (Exception e) {
    
                }
                return null;
            }
        }
    

    在for循环中开启了一百个异步任务,每个任务打印从0到99,每次打印sleep10毫秒,发现结果出乎意料:

    03-29 16:36:09.323 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]0
    03-29 16:36:09.334 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]1
    03-29 16:36:09.344 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]2
    03-29 16:36:09.354 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]3
    03-29 16:36:09.365 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]4
    03-29 16:36:09.375 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]5
    03-29 16:36:09.385 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]6
    03-29 16:36:09.396 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]7
    03-29 16:36:09.406 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]8
    03-29 16:36:09.416 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]9
    03-29 16:36:09.426 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]10
    03-29 16:36:09.437 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]11
    03-29 16:36:09.447 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]12
    03-29 16:36:09.457 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]13
    03-29 16:36:09.468 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]14
    03-29 16:36:09.478 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]15
    03-29 16:36:09.488 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]16
    03-29 16:36:09.499 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]17
    03-29 16:36:09.509 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]18
    03-29 16:36:09.520 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]19
    03-29 16:36:09.531 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]20
    03-29 16:36:09.541 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]21
    03-29 16:36:09.552 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]22
    03-29 16:36:09.562 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]23
    03-29 16:36:09.573 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]24
    03-29 16:36:09.583 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]25
    03-29 16:36:09.594 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]26
    03-29 16:36:09.606 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]27
    03-29 16:36:09.617 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]28
    03-29 16:36:09.627 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]29
    03-29 16:36:09.638 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]30
    03-29 16:36:09.649 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]31
    03-29 16:36:09.659 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]32
    03-29 16:36:09.670 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]33
    03-29 16:36:09.681 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]34
    03-29 16:36:09.692 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]35
    03-29 16:36:09.703 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]36
    03-29 16:36:09.713 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]37
    03-29 16:36:09.724 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]38
    03-29 16:36:09.734 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]39
    03-29 16:36:09.745 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]40
    03-29 16:36:09.755 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]41
    03-29 16:36:09.766 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]42
    03-29 16:36:09.776 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]43
    03-29 16:36:09.787 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]44
    03-29 16:36:09.797 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]45
    03-29 16:36:09.808 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]46
    03-29 16:36:09.818 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]47
    03-29 16:36:09.828 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]48
    03-29 16:36:09.839 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]49
    03-29 16:36:09.849 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]50
    03-29 16:36:09.860 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]51
    03-29 16:36:09.870 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]52
    03-29 16:36:09.880 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]53
    03-29 16:36:09.891 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]54
    03-29 16:36:09.902 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]55
    03-29 16:36:09.913 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]56
    03-29 16:36:09.923 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]57
    03-29 16:36:09.934 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]58
    03-29 16:36:09.944 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]59
    03-29 16:36:09.955 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]60
    03-29 16:36:09.965 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]61
    03-29 16:36:09.976 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]62
    03-29 16:36:09.986 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]63
    03-29 16:36:09.997 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]64
    03-29 16:36:10.007 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]65
    03-29 16:36:10.018 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]66
    03-29 16:36:10.028 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]67
    03-29 16:36:10.038 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]68
    03-29 16:36:10.049 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]69
    03-29 16:36:10.059 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]70
    03-29 16:36:10.070 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]71
    03-29 16:36:10.080 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]72
    03-29 16:36:10.091 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]73
    03-29 16:36:10.101 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]74
    03-29 16:36:10.112 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]75
    03-29 16:36:10.122 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]76
    03-29 16:36:10.133 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]77
    03-29 16:36:10.143 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]78
    03-29 16:36:10.153 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]79
    03-29 16:36:10.164 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]80
    03-29 16:36:10.174 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]81
    03-29 16:36:10.184 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]82
    03-29 16:36:10.195 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]83
    03-29 16:36:10.206 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]84
    03-29 16:36:10.216 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]85
    03-29 16:36:10.227 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]86
    03-29 16:36:10.237 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]87
    03-29 16:36:10.248 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]88
    03-29 16:36:10.258 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]89
    03-29 16:36:10.269 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]90
    03-29 16:36:10.279 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]91
    03-29 16:36:10.290 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]92
    03-29 16:36:10.301 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]93
    03-29 16:36:10.311 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]94
    03-29 16:36:10.322 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]95
    03-29 16:36:10.332 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]96
    03-29 16:36:10.343 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]97
    03-29 16:36:10.353 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]98
    03-29 16:36:10.364 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]99
    03-29 16:36:10.375 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]0
    03-29 16:36:10.386 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]1
    03-29 16:36:10.396 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]2
    03-29 16:36:10.407 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]3
    03-29 16:36:10.417 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]4
    03-29 16:36:10.428 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]5
    03-29 16:36:10.438 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]6
    03-29 16:36:10.448 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]7
    03-29 16:36:10.459 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]8
    03-29 16:36:10.469 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]9
    03-29 16:36:10.480 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]10
    03-29 16:36:10.491 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]11
    03-29 16:36:10.502 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]12
    03-29 16:36:10.512 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]13
    03-29 16:36:10.523 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]14
    03-29 16:36:10.534 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]15
    03-29 16:36:10.544 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]16
    03-29 16:36:10.555 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]17
    03-29 16:36:10.565 10746-10813/com.example.rzm.appmarket I/System.out: threadThread[AsyncTask #4,5,main]18
    ......
    

    在一个AsyncTask执行完成之前,另一个任务不会开始,也就是目前仍然,AsyncTask只能同时执行一个后台线程

    接下来看源码

    我们把AsyncTask的几个方法作为源码阅读的入口

    execute 开始执行
    cancel 取消执行
    

    execute

    //@MainThread 只能在主线程中开启
    @MainThread
        public final AsyncTask<Params, Progress, Result> execute(Params... params) {
            return executeOnExecutor(sDefaultExecutor, params);
        }
    

    我们知道,AsyncTask是通过线程池,Handler,Runnable集合来处理的,sDefaultExecutor继承自Executor,用来处理异步任务

    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
    ......
    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
    
    ......
    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() {
                        try {
                            r.run();
                        } finally {
                            scheduleNext();
                        }
                    }
                });
                if (mActive == null) {
                    scheduleNext();
                }
            }
    
            protected synchronized void scheduleNext() {
                if ((mActive = mTasks.poll()) != null) {
                    THREAD_POOL_EXECUTOR.execute(mActive);
                }
            }
        }
    

    executeOnExecutor

    @MainThread
        public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
                Params... params) {
            //判断当前任务的状态,如果不是未开始执行,而是正在执行或者已经执行
            //完成就抛出异常,所以一个任务只能执行一次,这就是一个任务调用两次execute方法会报错的原因
            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,重写此方法可进行一些初始化操作
            onPreExecute();
            //将参数存入worker的数组中
            mWorker.mParams = params;
            //这个exec就是刚刚传入的那个线程池类sDefaultExecutor,
            //将mFuture传入,执行sDefaultExecutor的execute方法
            exec.execute(mFuture);
    
            return this;
        }
    

    这里看到了一个mFuture,这个mFuture是什么呢,它是在AsyncTask的构造方法中初始化的

    public AsyncTask(@Nullable Looper callbackLooper) {
            mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
                ? getMainHandler()
                : new Handler(callbackLooper);
    
            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;
                }
            };
    
            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);
                    }
                }
            };
        }
    

    构造方法中初始化了一个Handler,用于接收子线程的消息,mWorker和mFuture是结合在一起使用的,mWorker是一种继承自Callable实现的线程,这种线程不同于Runnable和Thread,第一,可以有返回值,第二,可以抛出异常信息

    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
            //之前传入的参数就是存在这里的
            Params[] mParams;
        }
    

    FutureTask对Callable进行了一层包装,以保证这个线程可以被线程池执行,exec.execute(mFuture)线程池execute方法可以接受一个FutureTask对象

    我们回到线程池Executor的execute方法中

    private static class SerialExecutor implements Executor {
            final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
            Runnable mActive;
    
            public synchronized void execute(final Runnable r) {
                //execute方法执行,将这个Runnable任务加入mTasks
                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);
                }
            }
        }
    

    我们可以看到ArrayDeque是一个集合

    public class ArrayDeque<E> extends AbstractCollection<E>
    

    mTasks.offer是将这个任务加入了集合的尾部,相当于一个任务队列,

    public boolean offer(E e) {
            return offerLast(e);
        }
    
    /**
         * Inserts the specified element at the end of this deque.
         *
         * @param e the element to add
         * @return {@code true} (as specified by {@link Deque#offerLast})
         * @throws NullPointerException if the specified element is null
         */
        public boolean offerLast(E e) {
            addLast(e);
            return true;
        }
    

    看到这里我们已经接近了为什么AsyncTask只能同时执行一个任务这个问题的答案了,看这里

    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
    ......
    
    private static class SerialExecutor implements Executor {
            final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
            Runnable mActive;
    
            public synchronized void execute(final Runnable r) {
    
                //这里的操作只是将Runnable加入了mTasks
                mTasks.offer(new Runnable() {
                    public void run() {
                        try {
                            r.run();
                        } finally {
                            scheduleNext();
                        }
                    }
                });
                //任务加入集合之后,执行这个方法,使用线程池
                //来执行集合中的runnable任务,THREAD_POOL_EXECUTOR.execute(mActive);
                
                if (mActive == null) {
                    scheduleNext();
                }
            }
    
            protected synchronized void scheduleNext() {
                if ((mActive = mTasks.poll()) != null) {
                    THREAD_POOL_EXECUTOR.execute(mActive);
                }
            }
        }
    

    SerialExecutor是一个静态类,那么一旦初始化之后就会一直存在了,所有的AysyncTask共享这一个Executor,在第一个任务加入线程队列之后,取出第一个task开始执行第一个任务,并且给mActive附了值,此时mActive已经不再满足mActive==null的判断条件,也就是,在这个任务执行完成之前,如果有新的任务过来被加入任务队列,那么由于mActive==null的条件不成立,scheduleNext方法没法执行,这个任务就不会马上被执行,而是等待上一个任务完成之后再次调用scheduleNext开启下一个任务

    当第一个Runnable中的异步任务执行完成的时候,会再执行scheduleNext()方法,从线程队列中取出下一个任务开始执行,所以说AsyncTask的任务执行顺序就是加入线程队列的前后顺序,到这里,最初的问题解决了,AsyncTask的确是一次只能同时执行一个任务

    大概有人看到这里会觉得疑惑,对于这句话”当第一个Runnable中的异步任务执行完成的时候,会再执行scheduleNext()方法“中的Runnable中的异步任务指的是什么觉得不解,如果刚才的流程还记得的话,你会知道这个Runnable中的异步任务其实就是exec.execute(mFuture)传过来的FutureTask中包装的Callable,FutureTask也是最终实现了Runnable接口,所以r.run()中的r就是这个FutureTask。那么既然是异步任务,为什么要说当他执行完成的时候才会执行scheduleNext方法呢,按常理讲,应该是同时进行的,这里就涉及到了Callable线程的一种特性

    Callable线程运行过程中,会阻塞当前线程,直到执行完成获得执行结果

    这也是为什么将Runnable往线程队列中加的时候,要在这个Callable线程的外边再加一个Runnable,为什么不直接把这个Callable加入队列中,因为Callable有这个特性,导致他执行的时候会阻塞当前线程,那么如果直接加入集合,执行的时候直接执行这个Callable,那么就会导致主线程被阻塞,因为当前还是主线程,所以必须在Runnable中执行这个Callable

    所以当他运行的时候,当前线程被阻塞,那么

    finally {
           scheduleNext();
    }
    

    不会被立即执行,而是等待他执行完成,一个任务执行完成之后,调用scheduleNext执行下一个任务

    这时候我们再回到WorkerRunnable中,这里就是每一个任务执行的地方

    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
                        //回调doInBackground方法,执行我们的异步任务
                        result = doInBackground(mParams);
                        Binder.flushPendingCommands();
                    } catch (Throwable tr) {
                        mCancelled.set(true);
                        throw tr;
                    } finally {
                        postResult(result);
                    }
                    return result;
                }
            };
    

    当任务执行完成后,执行finally中的postResult方法,发送消息到Handler主线程

    private Result postResult(Result result) {
            @SuppressWarnings("unchecked")
            Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                    new AsyncTaskResult<Result>(this, result));
            message.sendToTarget();
            return result;
        }
    
    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]);
                        break;
                    case MESSAGE_POST_PROGRESS:
                        result.mTask.onProgressUpdate(result.mData);
                        break;
                }
            }
        }
    

    调用AsyncTask的finish方法,并传递任务执行结果

    private void finish(Result result) {
            if (isCancelled()) {
                onCancelled(result);
            } else {
                //回调onPostExecute,一个任务完成
                onPostExecute(result);
            }
            mStatus = Status.FINISHED;
        }
    

    下面我们再从cancel方法这个切入点去看源码

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

    调用的是FutureTask的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 {
                finishCompletion();
            }
            return true;
        }
    

    finishCompletion

    private void finishCompletion() {
            // assert state > COMPLETING;
            for (WaitNode q; (q = waiters) != null;) {
                if (U.compareAndSwapObject(this, WAITERS, q, null)) {
                    for (;;) {
                        Thread t = q.thread;
                        if (t != null) {
                            q.thread = null;
                            LockSupport.unpark(t);
                        }
                        WaitNode next = q.next;
                        if (next == null)
                            break;
                        q.next = null; // unlink to help gc
                        q = next;
                    }
                    break;
                }
            }
            
            done();
    
            callable = null;        // to reduce footprint
        }
    

    最终还是走到done方法中

    相关文章

      网友评论

          本文标题:06.源码阅读(AsyncTask深度分析-api26)

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