码迷,mamicode.com
首页 > 移动开发 > 详细

Android 源码分析01_AsyncTask

时间:2015-11-02 17:13:06      阅读:276      评论:0      收藏:0      [点我收藏+]

标签:

【参考文献】

http://blog.csdn.net/singwhatiwanna/article/details/17596225

 

  1 /*
  2  * Copyright (C) 2008 The Android Open Source Project
  3  *
  4  * Licensed under the Apache License, Version 2.0 (the "License");
  5  * you may not use this file except in compliance with the License.
  6  * You may obtain a copy of the License at
  7  *
  8  *      http://www.apache.org/licenses/LICENSE-2.0
  9  *
 10  * Unless required by applicable law or agreed to in writing, software
 11  * distributed under the License is distributed on an "AS IS" BASIS,
 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  * See the License for the specific language governing permissions and
 14  * limitations under the License.
 15  */
 16 
 17 package android.os;
 18 
 19 import java.util.ArrayDeque;
 20 import java.util.concurrent.BlockingQueue;
 21 import java.util.concurrent.Callable;
 22 import java.util.concurrent.CancellationException;
 23 import java.util.concurrent.Executor;
 24 import java.util.concurrent.ExecutionException;
 25 import java.util.concurrent.FutureTask;
 26 import java.util.concurrent.LinkedBlockingQueue;
 27 import java.util.concurrent.ThreadFactory;
 28 import java.util.concurrent.ThreadPoolExecutor;
 29 import java.util.concurrent.TimeUnit;
 30 import java.util.concurrent.TimeoutException;
 31 import java.util.concurrent.atomic.AtomicBoolean;
 32 import java.util.concurrent.atomic.AtomicInteger;
 33 
 34 public abstract class AsyncTask<Params, Progress, Result> {
 35     private static final String LOG_TAG = "AsyncTask";
 36 
 37     //获取当前的cpu核心数
 38     private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
 39     //线程池核心容量
 40     private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
 41     //线程池最大容量
 42     private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
 43     //过剩的空闲线程的存活时间
 44     private static final int KEEP_ALIVE = 1;
 45     //ThreadFactory 线程工厂,通过工厂方法newThread来获取新线程
 46     private static final ThreadFactory sThreadFactory = new ThreadFactory() {
 47         //原子整数,可以在超高并发下正常工作
 48         private final AtomicInteger mCount = new AtomicInteger(1);
 49 
 50         public Thread newThread(Runnable r) {
 51             return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
 52         }
 53     };
 54     //静态阻塞式队列,用来存放待执行的任务,初始容量:128个
 55     private static final BlockingQueue<Runnable> sPoolWorkQueue =
 56             new LinkedBlockingQueue<Runnable>(128);
 57 
 58     /**
 59      * 静态并发线程池,可以用来并行执行任务,尽管从3.0开始,AsyncTask默认是串行执行任务
 60      * 但是我们仍然能构造出并行的AsyncTask
 61      */
 62     public static final Executor THREAD_POOL_EXECUTOR
 63             = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
 64                     TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
 65 
 66     /**
 67      * 静态串行任务执行器,其内部实现了串行控制,
 68      * 循环的取出一个个任务交给上述的并发线程池去执行
 69      */
 70     public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
 71     //消息类型:发送结果
 72     private static final int MESSAGE_POST_RESULT = 0x1;
 73     //消息类型:更新进度
 74     private static final int MESSAGE_POST_PROGRESS = 0x2;
 75     /**静态Handler,用来发送上述两种通知,采用UI线程的Looper来处理消息
 76      * 这就是为什么AsyncTask必须在UI线程调用,因为子线程
 77      * 默认没有Looper无法创建下面的Handler,程序会直接Crash
 78      */
 79     private static final InternalHandler sHandler = new InternalHandler();
 80     //默认任务执行器,被赋值为串行任务执行器,就是它,AsyncTask变成串行的了
 81     private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
 82     //如下两个变量我们先不要深究,不影响我们对整体逻辑的理解
 83     private final WorkerRunnable<Params, Result> mWorker;
 84     private final FutureTask<Result> mFuture;
 85     //任务的状态 默认为挂起,即等待执行,其类型标识为易变的(volatile)
 86     private volatile Status mStatus = Status.PENDING;
 87     //原子布尔型,支持高并发访问,标识任务是否被取消
 88     private final AtomicBoolean mCancelled = new AtomicBoolean();
 89     //原子布尔型,支持高并发访问,标识任务是否被执行过
 90     private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
 91 
 92     /*串行执行器的实现,我们要好好看看,它是怎么把并行转为串行的
 93      *目前我们需要知道,asyncTask.execute(Params ...)实际上会调用
 94      *SerialExecutor的execute方法,这一点后面再说明。也就是说:当你的asyncTask执行的时候,
 95      *首先你的task会被加入到任务队列,然后排队,一个个执行
 96      */
 97     private static class SerialExecutor implements Executor {
 98         //线性双向队列,用来存储所有的AsyncTask任务
 99         final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
100         //当前正在执行的AsyncTask任务
101         Runnable mActive;
102 
103         public synchronized void execute(final Runnable r) {
104             //将新的AsyncTask任务加入到双向队列中
105             mTasks.offer(new Runnable() {
106                 public void run() {
107                     try {
108                         //执行AsyncTask任务
109                         r.run();
110                     } finally {
111                         //当前AsyncTask任务执行完毕后,进行下一轮执行,如果还有未执行任务的话
112                         //这一点很明显体现了AsyncTask是串行执行任务的,总是一个任务执行完毕才会执行下一个任务
113                         scheduleNext();
114                     }
115                 }
116             });
117             //如果当前没有任务在执行,直接进入执行逻辑
118             if (mActive == null) {
119                 scheduleNext();
120             }
121         }
122 
123         protected synchronized void scheduleNext() {
124             //从任务队列中取出队列头部的任务,如果有就交给并发线程池去执行
125             if ((mActive = mTasks.poll()) != null) {
126                 THREAD_POOL_EXECUTOR.execute(mActive);
127             }
128         }
129     }
130 
131     /**
132      * 任务的三种状态
133      */
134     public enum Status {
135         /**
136          * 任务等待执行
137          */
138         PENDING,
139         /**
140          * 任务正在执行
141          */
142         RUNNING,
143         /**
144          * 任务已经执行结束
145          */
146         FINISHED,
147     }
148 
149     /** 隐藏API:在UI线程中调用,用来初始化Handler */
150     public static void init() {
151         sHandler.getLooper();
152     }
153 
154     /** 隐藏API:为AsyncTask设置默认执行器 */
155     public static void setDefaultExecutor(Executor exec) {
156         sDefaultExecutor = exec;
157     }
158 
159     /**
160      * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
161      */
162     public AsyncTask() {
163         mWorker = new WorkerRunnable<Params, Result>() {
164             public Result call() throws Exception {
165                 mTaskInvoked.set(true);
166 
167                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
168                 //noinspection unchecked
169                 return postResult(doInBackground(mParams));
170             }
171         };
172 
173         mFuture = new FutureTask<Result>(mWorker) {
174             @Override
175             protected void done() {
176                 try {
177                     postResultIfNotInvoked(get());
178                 } catch (InterruptedException e) {
179                     android.util.Log.w(LOG_TAG, e);
180                 } catch (ExecutionException e) {
181                     throw new RuntimeException("An error occured while executing doInBackground()",
182                             e.getCause());
183                 } catch (CancellationException e) {
184                     postResultIfNotInvoked(null);
185                 }
186             }
187         };
188     }
189 
190     private void postResultIfNotInvoked(Result result) {
191         final boolean wasTaskInvoked = mTaskInvoked.get();
192         if (!wasTaskInvoked) {
193             postResult(result);
194         }
195     }
196     //doInBackground执行完毕,发送消息
197     private Result postResult(Result result) {
198         @SuppressWarnings("unchecked")
199         Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
200                 new AsyncTaskResult<Result>(this, result));
201         message.sendToTarget();
202         return result;
203     }
204 
205     /**
206      * 返回任务的状态
207      */
208     public final Status getStatus() {
209         return mStatus;
210     }
211 
212     /**
213      * 这个方法是我们必须要重写的,用来做后台计算
214      * 所在线程:后台线程
215      */
216     protected abstract Result doInBackground(Params... params);
217 
218     /**
219      * 在doInBackground之前调用,用来做初始化工作
220      * 所在线程:UI线程
221      */
222     protected void onPreExecute() {
223     }
224 
225     /**
226      * 在doInBackground之后调用,用来接受后台计算结果更新UI
227      * 所在线程:UI线程
228      */
229     protected void onPostExecute(Result result) {
230     }
231 
232     /**
233      * Runs on the UI thread after {@link #publishProgress} is invoked.
234      /**
235      * 在publishProgress之后调用,用来更新计算进度
236      * 所在线程:UI线程
237      */
238     protected void onProgressUpdate(Progress... values) {
239     }
240 
241      /**
242      * cancel被调用并且doInBackground执行结束,会调用onCancelled,表示任务被取消
243      * 这个时候onPostExecute不会再被调用,二者是互斥的,分别表示任务取消和任务执行完成
244      * 所在线程:UI线程
245      */
246     @SuppressWarnings({"UnusedParameters"})
247     protected void onCancelled(Result result) {
248         onCancelled();
249     }    
250     
251     protected void onCancelled() {
252     }
253 
254     public final boolean isCancelled() {
255         return mCancelled.get();
256     }
257 
258     public final boolean cancel(boolean mayInterruptIfRunning) {
259         mCancelled.set(true);
260         return mFuture.cancel(mayInterruptIfRunning);
261     }
262 
263     public final Result get() throws InterruptedException, ExecutionException {
264         return mFuture.get();
265     }
266 
267     public final Result get(long timeout, TimeUnit unit) throws InterruptedException,
268             ExecutionException, TimeoutException {
269         return mFuture.get(timeout, unit);
270     }
271 
272     /**
273      * 这个方法如何执行和系统版本有关,在AsyncTask的使用规则里已经说明,如果你真的想使用并行AsyncTask,
274      * 也是可以的,只要稍作修改
275      * 必须在UI线程调用此方法
276      */
277     public final AsyncTask<Params, Progress, Result> execute(Params... params) {
278         //串行执行
279         return executeOnExecutor(sDefaultExecutor, params);
280         //如果我们想并行执行,这样改就行了,当然这个方法我们没法改
281         //return executeOnExecutor(THREAD_POOL_EXECUTOR, params);
282     }
283 
284     /**
285      * 通过这个方法我们可以自定义AsyncTask的执行方式,串行or并行,甚至可以采用自己的Executor
286      * 为了实现并行,我们可以在外部这么用AsyncTask:
287      * asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Params... params);
288      * 必须在UI线程调用此方法
289      */
290     public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
291             Params... params) {
292         if (mStatus != Status.PENDING) {
293             switch (mStatus) {
294                 case RUNNING:
295                     throw new IllegalStateException("Cannot execute task:"
296                             + " the task is already running.");
297                 case FINISHED:
298                     throw new IllegalStateException("Cannot execute task:"
299                             + " the task has already been executed "
300                             + "(a task can be executed only once)");
301             }
302         }
303 
304         mStatus = Status.RUNNING;
305         //这里#onPreExecute会最先执行
306         onPreExecute();
307 
308         mWorker.mParams = params;
309         //然后后台计算#doInBackground才真正开始
310         exec.execute(mFuture);
311         //接着会有#onProgressUpdate被调用,最后是#onPostExecute
312 
313         return this;
314     }
315 
316     /**
317      * 这是AsyncTask提供的一个静态方法,方便我们直接执行一个runnable
318      */
319     public static void execute(Runnable runnable) {
320         sDefaultExecutor.execute(runnable);
321     }
322 
323     /**
324      * 打印后台计算进度,onProgressUpdate会被调用
325      */
326     protected final void publishProgress(Progress... values) {
327         if (!isCancelled()) {
328             sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
329                     new AsyncTaskResult<Progress>(this, values)).sendToTarget();
330         }
331     }
332 
333     //任务结束的时候会进行判断,如果任务没有被取消,则onPostExecute会被调用
334     private void finish(Result result) {
335         if (isCancelled()) {
336             onCancelled(result);
337         } else {
338             onPostExecute(result);
339         }
340         mStatus = Status.FINISHED;
341     }
342 
343     //AsyncTask内部Handler,用来发送后台计算进度更新消息和计算完成消息
344     private static class InternalHandler extends Handler {
345         @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
346         @Override
347         public void handleMessage(Message msg) {
348             AsyncTaskResult result = (AsyncTaskResult) msg.obj;
349             switch (msg.what) {
350                 case MESSAGE_POST_RESULT:
351                     // There is only one result
352                     result.mTask.finish(result.mData[0]);
353                     break;
354                 case MESSAGE_POST_PROGRESS:
355                     result.mTask.onProgressUpdate(result.mData);
356                     break;
357             }
358         }
359     }
360 
361     private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
362         Params[] mParams;
363     }
364 
365     @SuppressWarnings({"RawUseOfParameterizedType"})
366     private static class AsyncTaskResult<Data> {
367         final AsyncTask mTask;
368         final Data[] mData;
369 
370         AsyncTaskResult(AsyncTask task, Data... data) {
371             mTask = task;
372             mData = data;
373         }
374     }
375 }

 

Android 源码分析01_AsyncTask

标签:

原文地址:http://www.cnblogs.com/renzimu/p/4930582.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!