[TOC]
## 1、串行还是并行
实际后台线程只有一个,即所有的任务是串行的,即完成一个任务后再执行下一个任务,而非并行。
如果开多个任务,比如开三个任务,实际执行是串行的:
```
mAsyncTask task1 = new mAsyncTask();
mAsyncTask task2 = new mAsyncTask();
mAsyncTask task3 = new mAsyncTask();
task1.execute("1", "2", "3");
task2.execute("a", "b", "c");
task3.execute("x", "y", "z");
```
期望是任务线程并行的,如下:
![](https://img.kancloud.cn/b4/12/b412887e97a16a82e734255b369c17b7_495x428.png)
而实际情况是所有的线程都是串行的:
![](https://img.kancloud.cn/c8/77/c87764d1cd0a4717d8572c6fc10579b1_392x483.png)
异步任务是串行的,那么能不能并行呢?查阅资料发现是可以的。
在1.6之前,AsyncTask是串行执行任务的,1.6的时候AsyncTask开始采用线程池里处理并行任务,但是从3.0开始,为了避免AsyncTask所带来的并发错误,AsyncTask可以根据配置采用串行或并行执行任务,但是默认是采用一个线程来串行执行任务,若想并行执行任务,可以调用 executeOnExecutor (Executor exec, Params... params)方法。
该方法有两个参数,第一个是Executor ,第二个是任务参数,第一个是线程池实例,这里已经预定义了两种,AsyncTask.SERIAL_EXECUTOR和AsyncTask.THREAD_POOL_EXECUTOR,通过源代码可以看到,execute (Params... params)方法实际是调用的就是executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, params),即串行执行,如果想并行执行异步任务,可调用executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params)方法。
## 2、任务线程过多
异步任务并行处理时,AsyncTask最多可以同时执行的任务数量有限,同时队列中可以有128个在等待。 如果超过这个数字,就会报java.util.concurrent.RejectedExecutionException的异常(超出线程池容量以及队列长度后拒绝任务的策略)。
AsyncTask.THREAD_POOL_EXECUTOR线程池的配置如下:
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
其中:
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));//设置线程池的核心线程数2-4之间,但是取决于CPU核数
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);//等待队列,等待128个
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());
}
};
所以AsyncTask可能存在新开大量线程消耗系统资源和抛出异常,如没有捕获RejectedExecutionException异常会导致应用FC的风险。
访问网络频繁或者需要大量线程的程序应慎用AsyncTask。
## 3、生命周期
AsyncTask不与任何组件绑定生命周期,即在一个Activity中创建AsyncTask,当该Activity被销毁时AsyncTask并没有被同步销毁,而是在一直执行,直到doInBackground()方法执行完成。如果手动调用了cancel()方法,系统会自动调用onCancelled()方法,否则会执行onPostExecute()方法。
所以这里就会产生一个问题,Activity已经被销毁,而AsyncTask还在正常工作,还会对View做一些处理,但是此时的View已经不存在了。
所以应该确保在销毁Activity的同时,取消AsyncTask,即在Activity的onDestory()内调用cancel()方法。
## 4、任务执行结果丢失问题
当Activity重新创建时(屏幕旋转时或Activity意外销毁时恢复),AsyncTask任务正常运行,AsyncTask持有的销毁之前的Activity引用已经无效,而AsyncTask任务执行完成后,在onPostExecute()方法内修改UI也不会生效。
所以最好的办法是,当恢复Activity时重启AsyncTask任务。
## 5、内存泄漏
如果AsyncTask被声明为Activity的非静态内部类,那么AsyncTask会默认保留一个对该Activity的引用,如果这个Activity已经被销毁,因这种引用关系的存在,造成该Activity无法被回收,造成内存泄漏。
## 参考资料
[ AsyncTask存在的问题和缺陷](https://blog.csdn.net/haovin/article/details/90343595)
- Android
- 四大组件
- Activity
- Fragment
- Service
- 序列化
- Handler
- Hander介绍
- MessageQueue详细
- 启动流程
- 系统启动流程
- 应用启动流程
- Activity启动流程
- View
- view绘制
- view事件传递
- choreographer
- LayoutInflater
- UI渲染概念
- Binder
- Binder原理
- Binder最大数据
- Binder小结
- Android组件
- ListView原理
- RecyclerView原理
- SharePreferences
- AsyncTask
- Sqlite
- SQLCipher加密
- 迁移与修复
- Sqlite内核
- Sqlite优化v2
- sqlite索引
- sqlite之wal
- sqlite之锁机制
- 网络
- 基础
- TCP
- HTTP
- HTTP1.1
- HTTP2.0
- HTTPS
- HTTP3.0
- HTTP进化图
- HTTP小结
- 实践
- 网络优化
- Json
- ProtoBuffer
- 断点续传
- 性能
- 卡顿
- 卡顿监控
- ANR
- ANR监控
- 内存
- 内存问题与优化
- 图片内存优化
- 线下内存监控
- 线上内存监控
- 启动优化
- 死锁监控
- 崩溃监控
- 包体积优化
- UI渲染优化
- UI常规优化
- I/O监控
- 电量监控
- 第三方框架
- 网络框架
- Volley
- Okhttp
- 网络框架n问
- OkHttp原理N问
- 设计模式
- EventBus
- Rxjava
- 图片
- ImageWoker
- Gilde的优化
- APT
- 依赖注入
- APT
- ARouter
- ButterKnife
- MMKV
- Jetpack
- 协程
- MVI
- Startup
- DataBinder
- 黑科技
- hook
- 运行期Java-hook技术
- 编译期hook
- ASM
- Transform增量编译
- 运行期Native-hook技术
- 热修复
- 插件化
- AAB
- Shadow
- 虚拟机
- 其他
- UI自动化
- JavaParser
- Android Line
- 编译
- 疑难杂症
- Android11滑动异常
- 方案
- 工业化
- 模块化
- 隐私合规
- 动态化
- 项目管理
- 业务启动优化
- 业务架构设计
- 性能优化case
- 性能优化-排查思路
- 性能优化-现有方案
- 登录
- 搜索
- C++
- NDK入门
- 跨平台
- H5
- Flutter
- Flutter 性能优化
- 数据跨平台