AsyncTask源码解析
来源:互联网 发布:淘宝网儿童帽子 编辑:程序博客网 时间:2024/06/06 17:26
之前在项目上遇到一个bug,启动了异步线程,但是硬是没有执行,打印日志主线程中execute()方法前后都已经执行,只有AsyncTask的doInBackground中的日志没有打印出来。当时不明白是为何,后来在同事的指点下查看AsyncTask的源码,了解了AsyncTask原理就明白了。这里做下记录。
源码基于android6.0版本
直接进入AsyncTask的execute方法,看他是如何执行AsyncTask中各个方法的
public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); }...
<pre name="code" class="java"> 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赋值标识该task正在执行,在主线程执行了onPreExecute()方法,接下来出现了三个概念:mWorker,exec,mFuture。
/** * Creates a new asynchronous task. This constructor must be invoked on the UI thread. */ public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked return postResult(doInBackground(mParams)); } }; 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 occured while executing doInBackground()", e.getCause()); } catch (CancellationException e) { postResultIfNotInvoked(null); } } }; } private void postResultIfNotInvoked(Result result) { final boolean wasTaskInvoked = mTaskInvoked.get(); if (!wasTaskInvoked) { postResult(result); } } 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 abstract class WorkerRunnable<Params, Result> implements Callable<Result> { Params[] mParams; }
可见,在AsyncTask初始化时构造了mWorker和mFuture两个对象。可见mWorker存在一个call()方法,其中执行了doInBackground方法。exec是一个Executor接口对象,其execute方法应该是被继承了,先放着,到后面再看具体这个方法做了什么。mFuture是一个FutureTask对象,构造时将mWorker对象传入了,并且实现了done方法,其中执行了postResultNotInvoked()方法,该方法又通过get()传入了一个对象,进入FutureTask可知道这个get方法得到的就是传入的mWorker,代码就不贴出来了,postResultNotInvoked中发送了一个msg.what = MESSAGE_POST_RESULT,msg.obj = AsyncTaskResult的对象的message给了一个Handler执行,
private static class AsyncTaskResult<Data> { final AsyncTask mTask; final Data[] mData; AsyncTaskResult(AsyncTask task, Data... data) { mTask = task; mData = data; } }}可见这里的mTask就是当前的AsyncTask对象本身。看看message对象接收到消息后做了什么:
private static class InternalHandler extends Handler { public InternalHandler() { super(Looper.getMainLooper()); } @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; } } }... private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; }可见如果发送的是MESSAGE_POST_RESULT,就执行onPostExecute(),如果是传入的是MESSAGE_POST_PROGRESS(这个后面再分析),可见,mFuture中是封装了done()方法用于执行onPostExecute()。
到这里回顾一下我们的流程,那么我们只需要将onPreExecute方法执行以后的流程跟mWorker和mFuture两个对象中的call()和done()方法联系成一个整体就行了。从什么地方联系成一个整体呢?关键就在之前提到的exec.execute方法中。我们看下exec的实体sDefaultExecutor的定义:
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); } } }可见其execute方法中就是将一个Runnable对象加入的mTasks队列中,然后利用THREAD_POOL_EXECUTOR顺序执行mTasks任务池中的任务。看看这个THREAD_POOL_EXECUTOR是什么神圣
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);进入ThreadPoolExecutor的execute方法
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); /* * Proceed in 3 steps: * * 1. If fewer than corePoolSize threads are running, try to * start a new thread with the given command as its first * task. The call to addWorker atomically checks runState and * workerCount, and so prevents false alarms that would add * threads when it shouldn't, by returning false. * * 2. If a task can be successfully queued, then we still need * to double-check whether we should have added a thread * (because existing ones died since last checking) or that * the pool shut down since entry into this method. So we * recheck state and if necessary roll back the enqueuing if * stopped, or start a new thread if there are none. * * 3. If we cannot queue task, then we try to add a new * thread. If it fails, we know we are shut down or saturated * and so reject the task. */ int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) reject(command); else if (workerCountOf(recheck) == 0) addWorker(null, false); } else if (!addWorker(command, false)) reject(command); }...... private boolean addWorker(Runnable firstTask, boolean core) { retry: for (;;) { int c = ctl.get(); int rs = runStateOf(c); // Check if queue empty only if necessary. if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false; for (;;) { int wc = workerCountOf(c); if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) return false; if (compareAndIncrementWorkerCount(c)) break retry; c = ctl.get(); // Re-read ctl if (runStateOf(c) != rs) continue retry; // else CAS failed due to workerCount change; retry inner loop } } boolean workerStarted = false; boolean workerAdded = false; Worker w = null; try { w = new Worker(firstTask); final Thread t = w.thread; if (t != null) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { // Recheck while holding lock. // Back out on ThreadFactory failure or if // shut down before lock acquired. int rs = runStateOf(ctl.get()); if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { if (t.isAlive()) // precheck that t is startable throw new IllegalThreadStateException(); workers.add(w); int s = workers.size(); if (s > largestPoolSize) largestPoolSize = s; workerAdded = true; } } finally { mainLock.unlock(); } if (workerAdded) { t.start(); workerStarted = true; } } } finally { if (! workerStarted) addWorkerFailed(w); } return workerStarted; }这里其实就是将任务池中取出的任务放到一个Thread中,然后调用start启动这个线程,那么运行的就是这里的run方法
mTasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } });这里的r实际上就是之前的mFuture对象,最后答案即将揭晓,即看看mFuture中的run方法即可:
public void run() { if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) return; try { Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { result = c.call(); ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); } if (ran) set(result); } } finally { // runner must be non-null until state is settled to // prevent concurrent calls to run() runner = null; // state must be re-read after nulling runner to prevent // leaked interrupts int s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); } }真相大白,这里调用了c.call(),而这个c来自callable,这个callable就是mFuture初始化时构造函数中传入的mWorker
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable }回顾下mFuture的初始化传入的参数
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 occured while executing doInBackground()", e.getCause()); } catch (CancellationException e) { postResultIfNotInvoked(null); } } };
最后看下mFuture的done方法是在哪里执行的。可以想象应该是在mWorker.call()执行完之后调用的,其实就是在run方法里调用的set方法和setException方法
protected void set(V v) { if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) { outcome = v; UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state finishCompletion(); } } /** * Causes this future to report an {@link ExecutionException} * with the given throwable as its cause, unless this future has * already been set or has been cancelled. * * <p>This method is invoked internally by the {@link #run} method * upon failure of the computation. * * @param t the cause of failure */ protected void setException(Throwable t) { if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) { outcome = t; UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state finishCompletion(); } }....... private void finishCompletion() { // assert state > COMPLETING; for (WaitNode q; (q = waiters) != null;) { if (UNSAFE.compareAndSwapObject(this, waitersOffset, 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 }然后执行了mFuture的done方法,发送了消息给主线程的Handler处理,再执行onPostExecute方法。好的,至此基本流程分析完毕。总结下可以画个流程图:
- AsyncTask源码解析
- AsyncTask源码解析
- Android AsyncTask源码解析
- AsyncTask源码解析
- AsyncTask源码解析
- Android AsyncTask 源码解析
- Android AsyncTask 源码解析
- Android AsyncTask 源码解析
- Android AsyncTask 源码解析
- AsyncTask源码解析
- Android AsyncTask 源码解析
- AsyncTask源码解析
- AsyncTask源码解析
- Android AsyncTask 源码解析
- Android:AsyncTask源码解析
- Android AsyncTask源码解析
- AsyncTask源码解析
- AsyncTask源码解析
- linux下.o文件、.a文件、.so文件、.bin文件
- 第一次写博客 说说多态
- 割点和桥模板
- 欢迎使用CSDN-markdown编辑器
- iOS事件传递与响应者链
- AsyncTask源码解析
- 写在NOIP前
- ArrayList.remove()
- ab 模拟测试秒杀存在的问题
- ACM成绩转换
- JavaScript的数据类型
- cas server 在TOMCAT7 上 启动报错 invalid byte tag 的解决方案
- 浅谈WLAN干扰与抗干扰技术
- 素数有无穷个的证明