Asynctask的解析

来源:互联网 发布:手机网络加速设置 编辑:程序博客网 时间:2024/05/17 04:49
在我刚刚接触AsyncTask的时候我也很郁闷其中是怎么进行串行与并行的?在安卓的1.6以前其实本来是采用的串行执行任务,在1.6-3.0之间为了并发访问,安卓修改了能执行并行的,后来由于可以执行并行大家在很多地方都使用的导致线程创创建过多,所以在3.0以后又改为串行    在不同的地方new一个AsyncTask还能使用同一个线程池,后来查看源码我们可知道

查看源码可以知道Executor SERIAL_EXECUTOR是静态的随着类的的加载而加载,另外handler也是跟进程绑定的。
所以当我们执行下面的代码的时候是共享一个线程池和handler的

 new MyAsyncTask("AsyncTask#1").execute("");          new MyAsyncTask("AsyncTask#2").execute("");          new MyAsyncTask("AsyncTask#3").execute("");          new MyAsyncTask("AsyncTask#4").execute("");          new MyAsyncTask("AsyncTask#5").execute("");  

每次new AyncTask()都是创建一个任务,假如通知五个对象执行execute,那就给mTasks塞进去(offer)五个任务,然后走scheduleNext()方法,在这个 方法中mActive = mTasks.poll(),取出最前面那个执行,run方法走完了以后,走finaly{},这里面在取队列最前面的任务,以此往复。。。实现了串行。。。

public AsyncTask() {        mWorker = new WorkerRunnable<Params, Result>() {            public Result call() throws Exception {                mTaskInvoked.set(true);                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);                //noinspection unchecked                Result result = doInBackground(mParams);                Binder.flushPendingCommands();                return postResult(result);            }        };

然后将这个任务封装成进 mFuture = new FutureTask(mWorker) ;
每次拿着对象调用exectu();

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

然后这个任务就被扔给线程池SerialExecutor的实例。

 public static final Executor SERIAL_EXECUTOR = new SerialExecutor();//这里创建管理run的线程池    private static final int MESSAGE_POST_RESULT = 0x1;    private static final int MESSAGE_POST_PROGRESS = 0x2;    private static final InternalHandler sHandler = new InternalHandler();    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);            }        }    }

通过上面这个对任务runnable进行一次封装到mTasks集合里面, 第一次进去mActive==null然后执行了scheduleNext(),在这个方法里面我们把封装好的集合里的第一个任务赋值给mActive,这时候判断不为null,就去执行第二个线程池里的execute(run)方法scheduleNext(),然后把这个任务run方法结束的时候有个finaly{}在这个里面我们会再次调用,当这时候假如有别的任务加进来的话,这时候的又往mTasks后面(addLast)添加了任务,判断集合有任务的话在执行这个任务,这样就形成了一个串行的实现
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}

看串行的原理

 AsyncTask asyncTask=new AsyncTask() {            @Override            protected Object doInBackground(Object[] params) {                return null;            }        };
 asyncTask.execute(new Runnable() {            @Override            public void run() {            }        });
 public static final Executor SERIAL_EXECUTOR = new SerialExecutor();    private static final int MESSAGE_POST_RESULT = 0x1;    private static final int MESSAGE_POST_PROGRESS = 0x2;    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;//这里创建管理run的线程池    private static InternalHandler sHandler;    private final WorkerRunnable<Params, Result> mWorker;    private final FutureTask<Result> mFuture;    private volatile Status mStatus = Status.PENDING;    private final AtomicBoolean mCancelled = new AtomicBoolean();    private final AtomicBoolean mTaskInvoked = new AtomicBoolean();    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方法走的是这个方法,sDefaultExecutor默认的话使用的是sDefaultExecutor线程池。。。 而sDefaultExecutor是由SerialExecutor串行线程池new出来的,所以默认的情况下AsyncTask是串行的

SERIAL_EXECUTOR = new SerialExecutor(),
sDefaultExecutor = SERIAL_EXECUTOR;

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

那么我们有没有办法AsyncTask用并行的呢?
答案肯定是有的
怎么做?
AsyncTask为我们提供了一个Api,asyncTask.executeOnExecutor,其实这个也是asyncTask.execute(), 最终调用的方法。
这里面第一个参数就是我们自定义的线程池就可以实现了并行。。。

asyncTask.executeOnExecutor(Executor exec,            Params... params)
0 0
原创粉丝点击