IntentService使用及源码分析
HandlerThread源码分析
AsyncTask使用及封装实践
AsyncTask源码分析
上一篇博客,AsyncTask使用及封装实践 我们主要介绍了AsyncTask 的使用及封装实践,这一篇博客我们主要来讲解AsyncTask的源码
这篇博客主要讲解以下内容
讲解之前我们先来回顾一下AsyncTask的几个主要方法
在task 任务开始执行的时候调用,在doInBackground(Params… params)方法之前调用,在主线程中执行
- Result doInBackground(Params… params)
主要用来执行耗时操作,在子线程中执行,Params为我们参数的类型。而Result这个泛型,是我们返回的类型(可以是Integer,Long,String等等类型,只要不是八种基本类型就OK),同时 Result 的类型将作为 onPostExecute(Result result)的参数。
Void onProgressUpdate(Progress… values)
Runs on the UI thread after publishProgress(Progress…) is invoked. 当我们调用 publishProgress()方法的时候,会调用 onProgressUpdate()这个方法
Void onPostExecute(Result result)
在doInBackground()方法执行完毕之后,会调用这个方法,是在主线程中执行的。但如果我们手动调用了cancelled()方法,那么这个方法将不会被调用。
void onCancelled()
在Task
Executes the task with the specified parameters.当我们调用这个方法的时候,会执行任务
在指定的线程池里面执行Task
需要注意的是,Params,Progress,Result 并不是一种特定的类型,它其实是泛型,它支持除了八种基本类型之外的类型,跟普通的泛型一样。
当我们调用 execute()方法的时候,会紧接着调用我们的execeteOnExecutor(sDefaultExecutor, params)方法
在这个方法里面,会首先判断执行的状态的合法性,如果是finish或者running,会抛出异常,这也就是为什么AsyncTak只能被调用执行一次。紧接着会调用onPreExecute()方法
public final AsyncTask execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
public final AsyncTask 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;
}
接着会把当前的状态设置running状态,并把我们的params传递给我们的mWork。params=params;
那这个mWork是什么呢?
public AsyncTask() {
mWorker = new WorkerRunnable() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
mFuture = new FutureTask(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 occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
mWorker为AsyncTask的一个内部类
,实现了Callable接口,在call方法里面会调用我们的doInBackground方法,这也就是为什么我们的doInBackground。方法是在子线程里面执行的,执行完doInBackground()方法会把结构传递给我们的postResult(result)方法,在result方法,会调用handler发送消息,
接着再handler的handleMessage里面处理,在handleMessage里面,又会调用我们的 finish()方法,finish()方法里面会判断任务是否取消,如果被取消,会调用onCancelled(),否则会调用onPostExecute()方法。
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;
}
mFuture = new FutureTask(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 occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
postResultIfNotInvoked(get());get()表示获取mWorker的call的返回值,即Result。
然后看postResultIfNotInvoked方法。会判断是否已经将结果发送出去,即判断在mWork里面是否已经调用postResult(result)发送结果,没有的话调用再调用postResult(result)发送出去
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}
还记得上面exec.execute()吗?exec为executeOnExecutor(sDefaultExecutor,params)中的sDefaultExecutor
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static class SerialExecutor implements Executor {
final ArrayDeque mTasks = new ArrayDeque();
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);
}
}
}
可以看到sDefaultExecutor其实为SerialExecutor的一个实例,其内部维持一个任务队列;直接看其execute(Runnable runnable)方法,将runnable放入mTasks队尾;
判断当前mActive是否为空,为空则调用scheduleNext方法
scheduleNext方法里面,则直接取出任务队列中的队首任务,如果不为null则传入THREAD_POOL_EXECUTOR进行执行。
下面看THREAD_POOL_EXECUTOR为何方神圣:
Public static final Executor THREAD_POOL_EXECUTOR
=new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
可以看到就是一个自己设置参数的线程池,参数为:
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 ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
private static final BlockingQueue sPoolWorkQueue =
new LinkedBlockingQueue(128);
回顾一下sDefaultExecutor,真正在execute()中调用的为sDefaultExecutor.execute:
private static class SerialExecutor implements Executor {
final ArrayDeque mTasks = new ArrayDeque();
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);
}
}
}
可以看到,如果此时有10个任务同时调用execute(s synchronized)方法,第一个任务入队,然后在mActive = mTasks.poll()) != null被取出,并且赋值给mActivte,然后交给线程池去执行。然后第二个任务入队,但是此时mActive并不为null,并不会执行scheduleNext();所以如果第一个任务比较慢,10个任务都会进入队列等待;
真正执行下一个任务的时机是,线程池执行完成第一个任务以后,调用Runnable中的finally代码块中的scheduleNext,所以虽然内部有一个线程池,其实调用的过程还是线性的。一个接着一个的执行,相当于单线程。
这也就是我们在Result doInBackground(Params… params)方法里面调用 publishProgress()方法,会回调onProgressUpdate的原因
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult
缓存型池子,先查看池中有没有以前建立的线程,如果有,就reuse.如果没有,就建一个新的线程加入池中。能reuse的线程,必须是timeout IDLE内的池中线程,缺省timeout是60s,超过这个IDLE时长,线程实例将被终止及移出池。缓存型池子通常用于执行一些生存期很短的异步型任务 。
fixedThreadPool与cacheThreadPool差不多,也是能reuse就用,但不能随时建新的线程 其独特之处:任意时间点,最多只能有固定数目的活动线程存在,此时如果有新的线程要建立,只能放在另外的队列中等待,直到当前的线程中某个线程终止直接被移出池子。和cacheThreadPool不同:fixedThreadPool池线程数固定,但是0秒IDLE(无IDLE)。这也就意味着创建的线程会一直存在。所以fixedThreadPool多数针对一些很稳定很固定的正规并发线程,多用于服务器。
调度型线程池。这个池子里的线程可以按schedule依次delay执行,或周期执行 。0秒IDLE(无IDLE)。
单例线程,任意时间池中只能有一个线程 。用的是和cache池和fixed池相同的底层池,但线程数目是1-1,0秒IDLE(无IDLE)。
// 调用 executeOnExecutor,传入相应的线程池即可。
mDownloadTask.executeOnExecutor(Executors.newFixedThreadPool(4));
IntentService使用及源码分析
HandlerThread源码分析
AsyncTask使用及封装实践
AsyncTask源码分析
最后的最后,卖一下广告,欢迎大家关注我的微信公众号,扫一扫下方二维码或搜索微信号 stormjun,即可关注。 目前专注于 Android 开发,主要分享 Android开发相关知识和一些相关的优秀文章,包括个人总结,职场经验等。