Android并发编程之AsyncTask(异步任务)学习
[TOC]
概述
由于Android的特性,如果要执行耗时操作,则必须方法子线程中执行。如果在主线程中执行耗时操作那么会导致应用程序无法及时响应。除了Thread可以开启子线程外,Android中扮演线程角色的有很多。比如:AsyncTask和IntentService(开启任务线程执行耗时操作),同时HandlerThread(含有handler的Thread)也是一种特殊的线程。本篇文章主要介绍AsyncTask,一个执行异步任务的类,底层是采用线程池实现的。而IntentService和HandlerThread。他们的底层则直接使用了线程。
一、Android中的线程
在操作系统中,线程是操作系统调度的最小单元,同时线程又是一种受限的系统资源,即线程不可能无限制地产生,并且线程的创建和销毁都会有相应的开销。当系统中存在大量的线程时,系统会通过会时间片轮转的方式调度每个线程,因此线程不可能做到绝对的并行。
如果在一个进程中频繁地创建和销毁线程,显然不是高效的做法。正确的做法是采用线程池,一个线程池中会缓存一定数量的线程,通过线程池就可以避免因为频繁创建和销毁线程所带来的系统开销。关于线程池的理解,参考Java线程池详解,Android同样适用。
二、AsyncTask简介
AsyncTask是一个抽象类,它是由Android封装的一个轻量级异步类(轻量体现在使用方便、代码简洁),它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新UI。从实现上来讲,AsyncTask封装了Thread和Handler。通过AsyncTask可以更加方便的执行后台任务以及在主线程中访问UI。但是AsyncTask并不适合进行特别耗时的后台任务。这种情况下还是建议使用线程池比较好一些。
AsyncTask的内部封装了两个线程池(SerialExecutor和THREAD_POOL_EXECUTOR)和一个Handler(InternalHandler)。
其中SerialExecutor线程池用于任务的排队,让需要执行的多个耗时任务,按顺序排列,THREAD_POOL_EXECUTOR线程池才真正地执行任务,InternalHandler用于从工作线程切换到主线程。
1.AsyncTask的泛型参数
AsyncTask的类声明如下:
1 | public abstract class AsyncTask<Params, Progress, Result> |
有四个核心方法:
1 | onPreExcute() |
提炼总结
AsyncTask中有两个线程池(SerialExecutor和THREAD_POOL_EXECUTOR)和一个Handler(InternalHandler),其中线程池SerialExecutor用于任务的排队,而线程池THREAD_POOL_EXECUTOR用于真正地执行任务,InternalHandler用于将执行环境从线程池切换到主线程。
sHandler是一个静态的Handler对象,为了能够将执行环境切换到主线程,这就要求sHandler这个对象必须在主线程创建。由于静态成员会在加载类的时候进行初始化,因此这就变相要求AsyncTask的类必须在主线程中加载,否则同一个进程中的AsyncTask都将无法正常工作。