专栏名称: 蚂蚁金服ProtoTeam
数据前端团队
目录
相关文章推荐
前端之巅  ·  为什么2025/05/28和2025-05- ... ·  2 天前  
前端早读课  ·  【第3522期】扩展 React 服务端渲染的能力 ·  昨天  
前端早读课  ·  【招聘】抖音生活服务商品团队招前端实习生 ·  昨天  
程序员好物馆  ·  别再给所有函数起名叫 ... ·  2 天前  
程序员好物馆  ·  别再给所有函数起名叫 ... ·  2 天前  
前端早读课  ·  【第3521期】如何在 React 中构建一个库 ·  2 天前  
51好读  ›  专栏  ›  蚂蚁金服ProtoTeam

Android 源码分析(三)安卓中的线程

蚂蚁金服ProtoTeam  · 掘金  · 前端  · 2017-12-07 08:33

正文

请到「今天看啥」查看全文


这里 mHandler 被绑定了主线程的 Looper(如果你要用反射质量的方法强行。。。可以绑定子线程 Looper),然后就是一个 WorkerRunnable 和 FutureTask 对象。这两个类是线程相关的概念,不了解的可以去了解一下多线程篇,反正你记住,FutureTask的 run 方法里面会调用WorkerRunnable的 call 方法,所以 mWorker 的 call 方法会在线程池中被调用,也就是异步线程里面被调用。

接下来,我们就从 execute方法被调用开始吧

public final AsyncTask<Params, Progress, Result> execute(Params... params) {
	return executeOnExecutor(sDefaultExecutor, params);
}

这个方法比较简单,直接调用了executeOnExecutor方法,但是这里有个参数sDefaultExecutor 需要注意一下。先来看这个参数的定义:

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
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) {
        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);
        }
    }
}

从代码中我们可以看到sDefaultExecutor 是一个自定义的静态线程池,注意,是静态的哦,至于里面的逻辑,我们稍后再讲,先来看 executeOnExecutor 方法吧。

public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
        Params... params) {
    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();

    mWorker.mParams = params;
    exec.execute(mFuture);

    return this;
}

第一步:这个方法做了状态监测,一旦执行了这个方法 mStatus 状态就不再是 PENDING 了,所以当多次调用 execute 方法多次调用就会异常。 第二步:这个方法调用了onPreExecute 方法,注意,这里没有做任何线程切换,所以onPreExecute 方法回调和 execute 方法是在同一个线程。 第三步:把 params 赋值给mWorker.mParams,这个没什么好说的,大家记得mFuture的 run 方法会调用mWorker的 call 方法即可。 第四步:把构造方法里面的 mFuture 丢进了线程池里面,这个线程池就是刚刚我们说的sDefaultExecutor,现在,我们来看sDefaultExecutor线程池的代码吧。

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

这里大家可以看到,在execute(final Runnable r)方法里面的参数 r 就是mFuture,然后存到队列 mTask 里面去了,这里代码应该不太好理解,我直接根据结果分析原因了。就是为了保证mTasks队列里面的任务只能“串行”执行,也就是不允许并发。又因为这里是静态资源,独立与某个 AsyncTask,而每个 AsyncTask 的 mFuture又被保存在这里面,等待执行。所以,AsyncTask任务实际上是串行执行的哦。







请到「今天看啥」查看全文