AsyncTask的理解(一)

线程任务的调度

内部会创建一个进程作用域的线程池来管理要运行的任务,也就就是说当你调用了AsyncTask#execute()后,AsyncTask会把任务交给线程池,由线程池来管理创建Thread和运行Therad。对于内部的线程池不同版本的,Android的实现方式是不一样的:

Android2.3以前的版本,也即SDK/API 10和以前的版本。

内部的线程池限制是5个,也就是说最大只能同时开启5个线程工作(并行),超过了5个的话,其他的线程只能等待,直到有线程执行结束了,才能继续执行,内部默认使用的是THREAD_POOL_EXECUTOR线程池,这个也是AsyncTask的缺陷,对于android2.3以前这个是无法解决的。

android3.0之后,也就是SDK/API11和之后的版本。

Google也意识到了这个问题,因此做了一些调整,即#execute()后,任务是一个一个执行了,使用了SERIAL_EXECUTOR线程池执行任务:

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

sDefaultExecutor的源码如下:
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

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

扩展类AsyncTaskCompat

由于在3.0之后,google修改了Excutor的默认线程池为SERIAL_EXECUTOR,所以如果在3.0之后,要想使用平行5个的线程池,可以使用该类,当前前提最好是那种线程不超过5个,而又需要与UI进行交互的场景,也就是说该类可以让你回到2.3之前的效果。
其源代码如下:

public class AsyncTaskCompat {

        /**
        * Executes the task with the specified parameters, allowing multiple tasks to run in parallel
         * on a pool of threads managed by {@link android.os.AsyncTask}.
         *
         * @param task The {@link android.os.AsyncTask} to execute.
         * @param params The parameters of the task.
         * @return the instance of AsyncTask.
         */
        public static <Params, Progress, Result> AsyncTask<Params, Progress, Result> executeParallel(
                AsyncTask<Params, Progress, Result> task,
                Params... params) {
            if (task == null) {
                throw new IllegalArgumentException("task can not be null");
            }
            //进行版本的判断,如果是3.0之前,则直接使用task.execute(params);
            //AsyncTaskCompatHoneycomb.executeParallel(task, params)实际上是显示调用了线程池THREAD_POOL_EXECUTOR
            if (Build.VERSION.SDK_INT >= 11) {
                // From API 11 onwards, we need to manually select the THREAD_POOL_EXECUTOR
                AsyncTaskCompatHoneycomb.executeParallel(task, params);
            } else {
                // Before API 11, all tasks were run in parallel
                task.execute(params);
            }

            return task;
        }

    }
    //AsyncTaskCompatHoneycomb源码代码
    class AsyncTaskCompatHoneycomb {

        static <Params, Progress, Result> void executeParallel(
                AsyncTask<Params, Progress, Result> task,
                Params... params) {
            //这里显示调用了THREAD_POOL_EXECUTOR,所以就可以使用该线程池了
            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
        }

    }

其他

当然,对于想要自己规定线程池的个数,可以显示调用该方法:

 public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
                Params... params) {...}

我们只需要传入Executor即可,如使用自定义的CorePoolSize为开启7个线程的线程池:Executor(Executors.newFixedThreadPool(7))。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值