AsyncTask是一个很方便用来在主线程和工作线程切换任务的工具,但是如果用的不好会引入不少奇怪的问题
坑1:AsyncTask到底是并行还是串行
在回答这个 问题前,我们先看下官方对AsyncTask的注释,对AsyncTask有一个基本的了解
AsyncTask is designed to be a helper class around {@link Thread} and {@link Handler} * and does not constitute a generic threading framework. 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 thejava.util.concurrentpackage such as {@link Executor}, * {@link ThreadPoolExecutor} and {@link FutureTask}
从上面AsyncTask源码注释可以看出,AsyncTask只适合做短时间操作的任务(顶多几秒),长时间的操作不建议使用,但是why?
首先我们来看下最基础的AsyncTask的运行模型
对于一个AsyncTask任务执行时3个关键函数运行的环境如上图所示,这个没有太多的疑问。
那如果多个AsyncTask同时执行会有啥不一样的么?
先上结论:
同一进程内,多个AsyncTask 直接通过execute方法执行时,在android3.0以上是串行的
这就解答了源码注释里面的一个疑问,为什么AsyncTask只适合做短时间的操作。
因为他是串行执行的,如果前面的AsyncTask阻塞了,后面的AsyncTask就全部阻塞了。。。。。(多么痛的领悟)
我们来一起捋一捋代码,看看为啥得出这样的结论
作为一个可以提交多个任务 ,且可以在工作线程和主线程切换的工具类,必须有以下几个组成
1.线程池
2.事件队列
3.handler
先看线程池
一个最简单的AsyncTask方法写法应该是
new AsyncTask().execute();
我们看下execute方法的源码如下
里面有个sDefaultExecutor,一看就是一个线程池,我们来看下定义
线程池是一个静态变量,也就是说对于同一个进程来说,只会初始化一次,同一进程内的AsyncTask都运行在此进程池中。
真相大白了,从任务队列中一个个取出任务,执行完了再scheduleNext(),串行的执行任务。所以说千万不要在AsyncTask中执行长时间的任务