从用途上来讲,线程分为主线程和子线程,主线程主要处理和界面相关的事情,而子线程则往往用于执行耗时操作。
AsyncTask封装了线程池和Handler,它主要为了方便开发者在子线程中更新UI。HandlerThread是一种具有消息循环的线程,在它的内部可以使用Handler。IntentService是一个服务,系统对其进行了封装使其可以方便的执行后台任务,IntentService内部采用HandlerThread来执行任务,当任务完毕后IntentService会自动退出。
AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把进度和最终结果传递给主线程中更新UI。(不适合耗时任务,耗时任务可用线程池)
public abstract class AsyncTask<Params, Progress, Result>
提供了四个核心方法:
1. onPreExecute(),主线程中执行,在异步任务执行前被调用。
2. doInBackground(Params..params),在线程池中执行,用于异步任务,params表示异步任务的输入参数。
3. onProgressUpdate(Progress..values),主线程中执行,当后台任务执行进度改变被调用。
4. onPostExecute(Result result),在主线程中执行,在任务后被调用。
AsyncTask的条件限制:
1. AsyncTask的类必须在主线程中被加载。
2. AsyncTask的对象必须在主线程中被创建。
3. excute方法必须在UI线程中调用。
4. 不要在程序中直接使用onPreExecute,doInBackground,onProgressUpdate,onPostExecute方法。
5. 一个AsyncTask对象只能执行一次。
6. Android3.0以后采用一个线程串行执行任务
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
sDefaultExecutor实际上是一个串行的线程池。
下面分析线程池的执行过程:
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
AsyncTask有两个线程池(SerialExecutor 和 THREAD_POOL_EXECUTOR)和一个Handler,其中SerialExecutor 用于任务的排队,THREAD_POOL_EXECUTOR用于真正执行任务,IntentHandler用于将执行环境从线程池切换到主线程
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
sHandler是一个静态Handler对象,为了能够将执行环境切换到主线程,这就要求sHandler这个对象必须在主线程中创建。
HandlerThread继承了Thread,它是一种可以使用Handler的Thread,实现很简单,在run方法中通过Looper.prepare来创建消息duil,并通过Looper.loop来开启消息循环
IntentService是一种特殊的Service,它继承了Service并且它是一个抽象类,因此必须创建它的子类才能使用IntentService。
线程池的有点:
1. 重用线程池中的线程,避免线程的创建和销毁所带来的性能开销
2. 能有效控制线程池中的最大并发数,避免大量的线程之间因互相抢占系统资源而导致的阻塞现象。
3. 能够对线程进行简单的管理,并提供定时执行以及制定时间间隔循环执行等功能。
Java中的Executor是一个接口,真正的线程池的实现为ThreadPoolExecutor。
ThreadPoolExecutor分为四类:FixedThreadPool、CacheThreadPool、ScheduledThreadPool以及SingleThreadexecutor.