1.AsyncTask是封装好的线程池,比起Thread+Handler的方式,AsyncTask在操作UI线程上更方便,因为onPreExecute()、onPostExecute()及更新UI方法onProgressUpdate()均运行在主线程中,这样就不用Handler发消息处理了;
2.真正的缺点来自于AsyncTask的全局线程池只有5个工作线程,也就是说,一个APP如果运用AsyncTask技术来执行线程,那么同一时间最多只能有5个线程同时运行,其他线程将被阻塞(注:不运用AsyncTask执行的线程,也就是自己new出来的线程不受此限制),所以AsyncTask不要用于多线程取网络数据,因为很可能这样会产生阻塞,从而降低效率。
源码如下:
//获取当前的cpu核心数
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;
//静态阻塞式队列,用来存放待执行的任务,初始容量:128个
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
原来在SDK3.0以前的版本执行asyncTask.execute(task);时的确是多线程并发执行的,线程池大小为5,最大可大
128个,google在3.0以后的版本中做了修改,将asyncTask.execute(task);修改为了顺序执行,即只有当一个的实例
的任务完成后在执行下一个实例的任务。
3.0后新增了一个方法executeOnExecutor(Executor exec, Object... params),
该方法接受2个参数,第一个是Executor,第二个是任务参数。第一个是线程池实例,google为我们预定义了两种:
第一种是AsyncTask.SERIAL_EXECUTOR,第二种是AsyncTask.THREAD_POOL_EXECUTOR,顾名思义,第一
种其实就像3.0以后的execute方法,是顺序执行的。第二种就是3.0以前的execute方法,是可以并发执行的。
用asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);就可以多任务并发执行了。
既然executeOnExecutor第一个参数是Executor,那么我们可以自定义Executor,Executor主要由四
种类型newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor
asyncTask.executeOnExecutor(Executors.newFixedThreadPool(1), task);或者
asyncTask.executeOnExecutor(Executors.newSingleThreadExecutor, task);并没有像我想象的与
asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, task);那样是单线程顺序执行,而是像
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);是多线程并发执行的,我不是
已经规定newFixedThreadPool的线程池数量是1或者是newSingleThreadExecutor单线程了么!怎么回事呢?原来程
序在每次调用asyncTask.executeOnExecutor(Executors.newFixedThreadPool(2), task)时会获取一个新的Executor对
象,这个对象内的线程只执行对应的task,所以无论哪种情况每个task都有一个新的线程来执行,即并发执行。
知道原因就好办了,我们定义个一全局静态变量
private static ExecutorService exec = Executors.newSingleThreadExecutor();程序在每次调用
asyncTask.executeOnExecutor(exec, task);时是使用的同一个Executor
Java通过Executors提供四种线程池,分别为:
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。