Android的线程和线程池————读书笔记
Android的线程和线程池
从用途上来讲,线程分为主线程和子线程,主线程主要处理和界面相关的事情,而子线程则往往用于执行耗时操作。
AsyncTask封装了线程池和Handler,它主要为了方便开发者在子线程中更新UI。HandlerThread是一种具有消息循环的线程,在它的内部可以使用Handler。IntentService是一个服务,系统对其进行了封装使其可以方便的执行后台任务,IntentService内部采用HandlerThread来执行任务,当任务完毕后IntentService会自动退出。
Android中的线程形态
AsyncTask
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以后采用一个线程串行执行任务
AsyncTask的工作原理
@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
HandlerThread继承了Thread,它是一种可以使用Handler的Thread,实现很简单,在run方法中通过Looper.prepare来创建消息duil,并通过Looper.loop来开启消息循环
IntentService
IntentService是一种特殊的Service,它继承了Service并且它是一个抽象类,因此必须创建它的子类才能使用IntentService。
Android中的线程池
线程池的有点:
1. 重用线程池中的线程,避免线程的创建和销毁所带来的性能开销
2. 能有效控制线程池中的最大并发数,避免大量的线程之间因互相抢占系统资源而导致的阻塞现象。
3. 能够对线程进行简单的管理,并提供定时执行以及制定时间间隔循环执行等功能。
Java中的Executor是一个接口,真正的线程池的实现为ThreadPoolExecutor。
ThreadPoolExecutor分为四类:FixedThreadPool、CacheThreadPool、ScheduledThreadPool以及SingleThreadexecutor.
更多相关文章
- Android数据格式解析对象JSON用法
- 【Handler详解和例子】
- Android:子线程向UI主线程发送消息
- Android——智能指针
- 【Android】消息机制应用
- android 数据封装类-Parcelable 使用和学习
- Android(安卓)MVVM
- Android在开发中的实用技巧之Parcelable的使用以及如何传递复杂
- Android线程模型(Painless Threading) --- 转