AsyncTask8.0源码分析

本文深入剖析了Android中AsyncTask的源码,揭示了其内部的线程池、阻塞队列及任务执行机制。详细介绍了3.0版本前后AsyncTask在任务执行策略上的变化,包括串行与并行处理的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

public abstract class AsyncTask<Params, Progress, Result> {
    private static final String LOG_TAG = "AsyncTask";

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE_SECONDS = 30;

 private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);

.......................
}

在这里又看到了ThreadPoolExecutor,它的核心线程数是Math.max(2, Math.min(CPU_COUNT - 1, 4))个,线程池允许创建的最大线程数为CPU_COUNT * 2 + 1,非核心线程空闲等待新任务的最长时间为10秒。采用的阻塞队列是LinkedBlockingQueue,它的容量为128。3.0版本之前的AsyncTask有一个缺点就是,线程池最大的线程数为MAXIMUM_POOL_SIZE,加上阻塞队列的128个任务,所以AsyncTask最多能同时容纳128+MAXIMUM_POOL_SIZE个任务,当提交第128+MAXIMUM_POOL_SIZE+1任务时就会执行饱和策略,默认抛出RejectedExecutionException异常。

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

                }

            }

        };

    }

WorkerRunnable实现了Callable接口,在call中调用了doInBackground(mParams),最终调用postResult(result)。 FutureTask是一个可管理的异步任务,它实现Runnable和Future接口,它可以包装Runnable和Callable接口,给Executor执行。在这里 WorkerRunnable作为参数传给FutureTask,稍后会用到。执行会调用execute方法:

 @MainThread

    public final AsyncTask<Params, Progress, Result> execute(Params... params) {

        return executeOnExecutor(sDefaultExecutor, params);

    }

 

execute方法又调用executeOnExecutor方法:

    @MainThread

    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;

    }

这里先调用 onPreExecute方法,这里exec是传进来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);

            }

        }

    }

调用SerialExecutor的execute方法时,会将FutureTask加入到mTask中。最后执行 scheduleNext方法,他会从mTasks取出FutureTask交给 THREAD_POOL_EXECUTOR处理。

   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;

    }

从这里看出,serialExecutor是串行执行的。可以看到会执行FutureTask的run方法,最终执行WorkerRunnable的call方法。最终调用postResult方法:

    private Result postResult(Result result) {

        @SuppressWarnings("unchecked")

        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,

                new AsyncTaskResult<Result>(this, result));

        message.sendToTarget();

        return result;

    }

最终调用Handler:

    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;

            }

        }

在接收到MESSAGE_POST_RESULT,会调用finish方法

    private void finish(Result result) {

        if (isCancelled()) {

            onCancelled(result);

        } else {

            onPostExecute(result);

        }

        mStatus = Status.FINISHED;

    }

  如果AsyncTask任务被取消了则执行onCancelled方法,否则就调用onPostExecute方法。而正是通过onPostExecute方法我们才能够得到异步任务执行后的结果。 接着回头来看SerialExecutor ,线程池SerialExecutor主要用来处理排队,将任务串行处理。 SerialExecutor中调用scheduleNext方法时,将任务交给THREAD_POOL_EXECUTOR。THREAD_POOL_EXECUTOR同样是一个线程池,用来执行任务。

  THREAD_POOL_EXECUTOR指的就是threadPoolExecutor,他的核心线程和线程池允许创建的最大线程数都是由CPU的核数来计算出来的。它采用的阻塞队列仍旧是LinkedBlockingQueue,容量为128。 

  到此, AsyncTask的源码就分析完了,在AsyncTask中用到了线程池,线程池中运行线程并且又用到了阻塞队列,因此,本章前面介绍的知识在这一节中做了很好的铺垫。Android 3.0及以上版本用SerialExecutor作为默认的线程,它将任务串行的处理保证一个时间段只有一个任务执行,而3.0之前版本是并行处理的。关于3.0之前版本的缺点在3.0之后版本也不会出现,因为线程是一个接一个执行的,不会出现超过任务数而执行饱和策略。

如果想要在3.0及以上版本使用并行的线程处理可以使用如下的代码:asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");

内容概要:本文档是详尽的 Android SDK 中文帮助文档,介绍了 Android SDK 的核心概念、组件、开发环境搭建、基础开发流程及常用工具使用指南。首先解释了 Android SDK 的定义及其核心价值,即提供标准化开发环境,使开发者能高效构建、测试、优化 Android 应用。接着详细列出了 SDK 的核心组件,包括 Android Studio、SDK Tools、Platform Tools、Build Tools、Android 平台版本和系统镜像。随后,文档提供了详细的环境搭建步骤,适用于 Windows、macOS 和 Linux 系统,并介绍了基础开发流程,以“Hello World”为例展示了从创建项目到运行应用的全过程。此外,还深入讲解了 ADB、AVD Manager 和 SDK Manager 等核心工具的功能和使用方法。最后,文档涵盖了调试与优化工具(如 Logcat、Profiler 和 Layout Inspector)、关键开发技巧(如多版本 SDK 兼容、Jetpack 库的使用和资源文件管理)以及常见问题的解决方案。 适合人群:具有初步编程知识,希望深入了解 Android 应用开发的开发者,尤其是新手开发者和有一定经验但需要系统化学习 Android SDK 的技术人员。 使用场景及目标:①帮助开发者快速搭建 Android 开发环境;②指导开发者完成基础应用开发,理解核心工具的使用;③提高开发效率,掌握调试与优化技巧;④解决常见开发过程中遇到的问题。 阅读建议:此文档内容全面且实用,建议读者按照章节顺序逐步学习,结合实际开发项目进行练习,尤其要注意动手实践环境搭建和基础开发流程,同时参考提供的扩展学习资源,进一步提升开发技能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值