从头分析—源码解析

来源:互联网 发布:卖软件代理 编辑:程序博客网 时间:2024/05/16 12:05

ArrayDeque 这是一个集合

  • 实现了Deque接口的可变数组
  • 没有容量限制
  • 不是线程安全
  • 不支持多线程访问
  • 元素不能为null
  • 速度比stack和LinkedList快
    下面是累继承图:

简单介绍

  • AsyncTasks should ideally be used for short operations (a few seconds at the most.)
  • An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called onPreExecute, doInBackgroundonProgressUpdate and onPostExecute.

方法执行顺序

  • onPreExecute() -> doInBackground -> onPreExecute() -> publishProgress -> onProgressUpdate -> onPostExecute .

构造方法,必须在UI线程唤醒

public AsyncTask() {//WorkerRunnable实现了CallBack<result>接口,call就是需要实现的方法mWorker = new WorkerRunnable<Params, Result>() {public Result call() throws Exception {mTaskInvoked.set(true);//value = 1Result result = null;try {//Process就是底层OS过程管理工具//setTreadPriorith调用是native方法,设置优先级//linux的优先级是从-19到20区间Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);//noinspection unchecked//将参数传入处理结果得到resultresult = doInBackground(mParams);Binder.flushPendingCommands();} catch (Throwable tr) {mCancelled.set(true);throw tr;} finally {//并将result传出去postResult(result);}return result;}};/*** A cancellable asynchronous computation. This class provides a base* implementation of {@link Future}, with methods to start and cancel* a computation, query to see if the computation is complete, and* retrieve the result of the computation. The result can only be* retrieved when the computation has completed; the {@code get}* methods will block if the computation has not yet completed. Once* the computation has completed, the computation cannot be restarted* or cancelled (unless the computation is invoked using* {@link #runAndReset}).*/mFuture = new FutureTask<Result>(mWorker) {@Overrideprotected 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);}}};}

执行execute的方法,

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

调用executeOnExecutor(sDefaultExecutor, params);

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

其中有三种状态:

/*** Indicates the current status of the task. Each status will be set only once* during the lifetime of a task.*/public enum Status {/*** Indicates that the task has not been executed yet.*/PENDING,/*** Indicates that the task is running.*/RUNNING,/*** Indicates that {@link AsyncTask#onPostExecute} has finished.*/FINISHED,}
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() {//1public void run() {try {r.run();//2} finally {scheduleNext();}}});if (mActive == null) {scheduleNext();}}protected synchronized void scheduleNext() {if ((mActive = mTasks.poll()) != null) {THREAD_POOL_EXECUTOR.execute(mActive);}}}

从注释1处可以看出,当调用SerialExecutor 的execute方法时,会将FutureTask加入到mTasks中。当任务执行完或者当前没有活动的任务时都会执行scheduleNext方法,它会从mTasks取出FutureTask任务并交由THREAD_POOL_EXECUTOR处理。关于THREAD_POOL_EXECUTOR,后面会介绍。从这里看出SerialExecutor是串行执行的。在注释2处可以看到执行了FutureTask的run方法,它最终会调用WorkerRunnable的call方法。
前面我们提到call方法postResult方法将结果投递出去,postResult方法代码如下所示。

private Result postResult(Result result) {@SuppressWarnings("unchecked")Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,new AsyncTaskResult<Result>(this, result));message.sendToTarget();return result;}

在postResult方法中会创建Message,并将结果赋值给这个Message,通过getHandler方法得到Handler,并通过这个Handler发送消息,getHandler方法如下所示。

private static Handler getHandler() {synchronized (AsyncTask.class) {if (sHandler == null) {sHandler = new InternalHandler();}return sHandler;}}

在getHandler方法中创建了InternalHandler,InternalHandler的定义如下所示。

private static class InternalHandler extends Handler {public InternalHandler() {super(Looper.getMainLooper());}@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})@Overridepublic void handleMessage(Message msg) {AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;switch (msg.what) {case MESSAGE_POST_RESULT:// There is only one resultresult.mTask.finish(result.mData[0]);break;case MESSAGE_POST_PROGRESS:result.mTask.onProgressUpdate(result.mData);break;}}}

在接收到MESSAGE_POST_RESULT消息后会调用AsyncTask的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同样是一个线程池,用来执行任务。

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

THREAD_POOL_EXECUTOR指的就是threadPoolExecutor,他的核心线程和线程池允许创建的最大线程数都是由CPU的核数来计算出来的。它采用的阻塞队列仍旧是LinkedBlockingQueue,容量为128。如果想要在3.0及以上版本使用并行的线程处理可以使用如下的代码:

asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");

其中asyncTask是我们自定义的AsyncTask,当然也可以传入Java提供的线程池,比如传入CachedThreadPool。

asyncTask.executeOnExecutor(Executors.newCachedThreadPool(),"");

也可以传入自定义的线程池:

Executor exec =new ThreadPoolExecutor(0, Integer.MAX_VALUE,0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());asyncTask.executeOnExecutor(exec,"");
0 0
原创粉丝点击