0x4、演进历史
Android 1.6
详细源码:core/java/android/os/AsyncTask.java
改动如下:
// ① 只用到一个线程池,并行执行任务,配置如下 // 核心线程池→5、线程数最大值→128,非核心线程空闲存活时长→10s // 堵塞队列:LinkedBlockingQueue → 最大值10 // ② 消息类型有三种: // MESSAGE_POST_RESULT、MESSAGE_POST_PROGRESS、MESSAGE_POST_CANCEL // ③ 总结:5个核心线程 + 123个非核心线程 + 10个任务 → 最多138个任务,牛啊 // handler还需处理AsyncTask取消的消息,后续变成了一个标志位~
Android 3.2
详细源码:core/java/android/os/AsyncTask.java
改动如下:
// ① 用到了两个线程池,串行执行任务,配置如下: // 核心线程池-5、线程数最大值-128,非核心线程空闲存活时长-1s // 堵塞队列:LinkedBlockingQueue → 最大值10 // ② 串行线程池同9.0 // ③ 消息类型少了取消,通过判断mFuture.isCancelled()来判断取消状态
Android 4.4
详细源码:core/java/android/os/AsyncTask.java
改动如下:
// ① 同样是串行,配置不再粗暴写死,而是基于当前可用的处理器数量进行计算: private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); private static final int CORE_POOL_SIZE = CPU_COUNT + 1; private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; // ② 堵塞队列上限变成128 // ③ 提供了串行变并行的setDefaultExecutor(),但被注解为@hide
Android 7.0
详细源码:core/java/android/os/AsyncTask.java
改动如下:
// 动了下线程池配置,看注释 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; // ① 核心线程池改成了2到4之间,不再是粗暴的CPU_COUNT+1,避免极端情况下占用 // 所有CPU影响到其他后台线程的调度~ // ② 线程空闲时间也调整为30s // ③ 调用allowCoreThreadTimeOut(true),空闲时间过长连核心线程也会回收
Android 8.0
详细源码:core/java/android/os/AsyncTask.java
改动如下:
// 线程池没动,多了两个AsyncTask的构造方法,而且用了@hide注解 public AsyncTask(@Nullable Handler handler) { this(handler != null ? handler.getLooper() : null); } public AsyncTask(@Nullable Looper callbackLooper) { mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper() ? getMainHandler() : new Handler(callbackLooper); } // 这里猜测是为了扩展,支持外部传入一个Handler,做一些定制化处理,hide说明是想给系统自用的~
Android 10.0
上面的原理基于9.0讲解的,直接跳过讲10.0,详细源码:
core/java/android/os/AsyncTask.java
改动如下:
// ① 线程池策略,发生了变化: 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; public static final Executor THREAD_POOL_EXECUTOR; 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; } // ② 核心线程数→1、最大线程数→20、空闲线程存活时间→3s、堵塞队列变成了SynchronousQueue // 无缓冲等待队列(不存储元素的堵塞队列,添加元素后等待其他线程去走后才能继续添加) // ③ 没有采用ThreadPoolExecutor已有的拒绝策略,自定义了一种拒绝策略: private static final RejectedExecutionHandler sRunOnSerialPolicy = new RejectedExecutionHandler() { public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { android.util.Log.w(LOG_TAG, "Exceeded ThreadPoolExecutor pool size"); // As a last ditch fallback, run it on an executor with an unbounded queue. // Create this executor lazily, hopefully almost never. synchronized (this) { if (sBackupExecutor == null) { sBackupExecutorQueue = new LinkedBlockingQueue<Runnable>(); sBackupExecutor = new ThreadPoolExecutor( BACKUP_POOL_SIZE, BACKUP_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, sBackupExecutorQueue, sThreadFactory); sBackupExecutor.allowCoreThreadTimeOut(true); } } sBackupExecutor.execute(r); } }; // 定义了一个核心池和最大核心池都为5的线程池,当拒绝策略处理任务,最多可以另外开5个线程 // 来执行任务,如果还不够的话,会添加到一个几乎无限大的LinkedBlockingQueue队列中
Android 11.0
详细源码:core/java/android/os/AsyncTask.java
改动如下:
// 为AsyncTask 添加 @Deprecated注解,一些描述注释
0x5、小结
有关AsyncTask最后的提交定格在2019.12.19,时代的车轮只会滚滚向前,而我们终将化为一粒尘埃。了解源码可以看到工程师对线程池策略的不断调整,很适合背完Java并发八股文后学习巩固~