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

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

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

相关文章
|
2月前
|
数据采集 运维 数据挖掘
API电商接口大数据分析与数据挖掘 (商品详情店铺)
API接口、数据分析以及数据挖掘在商品详情和店铺相关的应用中,各自扮演着重要的角色。以下是关于它们各自的功能以及如何在商品详情和店铺分析中协同工作的简要说明。
|
3月前
|
资源调度 监控 API
开源API网关APISIX分析与使用
开源API网关APISIX分析与使用
179 0
|
3月前
|
API
GEE案例分析——利用sentinel-3数据计算空气污染指数(Air Pollution Index,简称API)
GEE案例分析——利用sentinel-3数据计算空气污染指数(Air Pollution Index,简称API)
115 0
|
5月前
|
Java Shell 分布式数据库
【大数据技术Hadoop+Spark】HBase数据模型、Shell操作、Java API示例程序讲解(附源码 超详细)
【大数据技术Hadoop+Spark】HBase数据模型、Shell操作、Java API示例程序讲解(附源码 超详细)
84 0
|
5月前
|
分布式计算 Java 大数据
【大数据技术Hadoop+Spark】HDFS Shell常用命令及HDFS Java API详解及实战(超详细 附源码)
【大数据技术Hadoop+Spark】HDFS Shell常用命令及HDFS Java API详解及实战(超详细 附源码)
242 0
|
数据采集 数据可视化 算法
电商API接口的大数据分析与挖掘技巧
随着电商行业的快速发展,电商平台上的交易数据量也越来越大。如何对这些数据进行分析和挖掘,从中获取有价值的信息,已经成为电商企业和开发者关注的重点。本文将介绍电商API接口的大数据分析与挖掘技巧。
|
12天前
|
存储 Java API
使用Stream API进行数据处理和分析
【4月更文挑战第18天】Java 8的Stream API为高效声明式处理集合数据提供了革命性功能。Stream非存储、不重复、有顺序且只能消费一次。创建Stream可通过集合、`Stream.of()`、`Stream.generate()`和`Stream.iterate()`。中间操作如`filter()`、`map()`和`sorted()`不改变原流,而终端操作如`forEach()`、`toArray()`和`collect()`结束流并产生结果。
|
22天前
|
存储 监控 BI
HIS系统是什么?一套前后端分离云HIS系统源码 接口技术RESTful API + WebSocket + WebService
医院管理信息系统(全称为Hospital Information System)即HIS系统。 常规模版包括门诊管理、住院管理、药房管理、药库管理、院长查询、电子处方、物资管理、媒体管理等,为医院管理提供更有力的保障。 HIS系统以财务信息、病人信息和物资信息为主线,通过对信息的收集、存储、传递、统计、分析、综合查询、报表输出和信息共享,及时为医院领导及各部门管理人员提供全面、准确的各种数据。 门诊医生工作站采用下拉式汉化菜单,界面友好,实用性强,设有与门诊挂号收费系统、医技科室信息系统、住院结算信息系统的软件接口。
28 1
|
2月前
|
移动开发 API HTML5
HTML5响应式自动采集API壁纸系统源码自适应手机端
HTML5响应式自动采集API壁纸系统源码自适应手机端
41 11
HTML5响应式自动采集API壁纸系统源码自适应手机端
|
4月前
|
缓存 供应链 安全
淘宝API接口调用:案例分析与最佳实践(续)
淘宝API接口是连接商家与淘宝平台强大功能的重要桥梁。通过案例分析和最佳实践的分享,我们希望商家能够更深入地理解如何有效地使用这些API来优化电商业务。随着技术的不断进步,淘宝API的功能将会越来越丰富,而商家面临的挑战也会越来越大。因此,商家需要不断地学习新技术、探索新方法,并且不断完善自己的API使用策略,以便更好地适应市场的变化,赢得竞争的优势。