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

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方法中

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351