在类的定义说明中有这样一句话
大概意思是你只能使用AsyncTask执行一些运行周期短的操作(最多只有几秒)如果是长周期的方法,最好使用Executor,ThreadPoolExecutor 等。
AsyncTasks should ideally be
* used for short operations (a few seconds at the most.) If you need to keep threads
* running for long periods of time, it is highly recommended you use the various APIs
* provided by the <code>java.util.concurrent</code> package such as {@link Executor},
* {@link ThreadPoolExecutor} and {@link FutureTask}
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
AsyncTask 执行execute的时候采用的是 sDefaultExecutor 作为executor,sDefaultExecutor默认的指向
/**
* An {@link Executor} that executes tasks one at a time in serial
* order. This serialization is global to a particular process.
*/
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
...
...
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);
}
}
}
这里很有意思,在SerialExecutor scheduleNext的方法里调用了 THREAD_POOL_EXECUTOR 的execute(mActive)
mActive 实际上是
new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
}
也就是AsyncTask通过 SerialExecutor 调度,使用 mTasks缓存,但是执行的时候,采用的是THREAD_POOL_EXECUTOR,大家不难看出,需要线程执行完毕的时候,才会在finally里走进scheduleNext(),继续执行。
在这里要说一下,如果没用过AsyncTask 的同学,可能没办法理解这个mTasks什么情况下会有缓存,会有多个值,大家可能注意到了 execute(Params... params),然后并不是这里。这个地方的参数params在后面会讲到,他是作为一个数组传递给了doInBackground方法。
那么这里是在什么情况下会有缓存数据呢?看下面定义
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
//大家看定义,这是一个静态的Executor也就是说进程中所有的AsyncTask都是通过同一个sDefaultExecutor 来调度的。
说到这里,大家可能明白了开篇说的那句话,如果执行时间比较长,那么AsyncTask的sDefaultExecutor就会被卡住,后面的任务都无法执行了。
在类的构造方法里,初始化了两个变量,其中一个是mWorker,他是一个Callable,他的call方法,执行了 result = doInBackground(mParams);并且最终调用了 postResult(result);通知用户。
mWorker = new WorkerRunnable<Params, Result>() {
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;
}
};
好了,就这样,先说到这里,大家感兴趣不防测试验证一下。
网友评论