public abstract class AsyncTask<Params, Progress, Result> {
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
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<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
/**
* An {@link Executor} that can be used to execute tasks in parallel.
*/
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;
}
/**
* 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 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);
}
}
}
}
上面的代码是AsyncTask的核心
AsyncTask 顾名思义 就是异步任务的意思 ,用来异步处理一些耗时长的任务,既然能处理异步任务,那么就会设计到线程的创建等
下面我们来分析一下其工作原理
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}
通过上面两个方法,可以启动AsyncTask去执行任务, 然后将任务丢到sDefaultExecutor (本质是上面的SerialExecutor),下面我们来分析一下SerialExecutor
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
//每次执行任务,首先将将Runnable 跑到mTasks中
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);
}
}
}
从上面代码我们可以知道:
1 调用AsyncTask execute本质是将需要执行的异步任务丢到串行的线程池(SerialExecutor)队列中,包裹一层,
2 SerialExecutor 的本质并不执行线程,只负责维护任务队列,并进行任务的分发
3 执行的执行线程是THREAD_POOL_EXECUTOR 来执行任务
4
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;
}
上面这段代码属于进程级别的,所以也就限制了,整个进程中无论创建多少AsyncTask,线程池的核心线程数就是2-4个,最大线程数为2 * CORE_POOL_SIZE + 1,等待队列的数量是128,所以在使用AsyncTask处理异步任务时,并发执行是受到一些限制的。
总结: AsyncTask 用来处理异步任务,但是其内部维护了两个进程级别的线程池, 其中SerialExecutor为了保证所有的任务都是串行开始的,THREAD_POOL_EXECUTOR 用来并发处理任务
缺点: 使用AsyncTask,整个进程中所有的任务都是串行的,对于高并发场景不适用。
Android sdk28之后:
/ We keep only a single pool thread around all the time.
// We let the pool grow to a fairly large number of threads if necessary,
// but let them time out quickly. In the unlikely case that we run out of threads,
// we fall back to a simple unbounded-queue executor.
// This combination ensures that:
// 1. We normally keep few threads (1) around.
// 2. We queue only after launching a significantly larger, but still bounded, set of threads.
// 3. We keep the total number of threads bounded, but still allow an unbounded set
// of tasks to be queued.
private static final int CORE_POOL_SIZE = 1;
private static final int MAXIMUM_POOL_SIZE = 20;
private static final int BACKUP_POOL_SIZE = 5;
private static final int KEEP_ALIVE_SECONDS = 3;
核心线程数1,最大线程数20
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), sThreadFactory);
threadPoolExecutor.setRejectedExecutionHandler(sRunOnSerialPolicy);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}