Android中规定, 只有在主线程中可以进行UI操作, 但是同时, 主线程中不能进行耗时操作,否则会产生ANR,因此耗时操作必须放到子线程中进行处理.
封装了线程池和Handler, 主要使用场景是在子线程中更新UI.
IntentService : 底层使用Thread 内部采用HandlerThread来执行任务,当任务执行完成后IntentService就会自动退出. 从任务执行的角度看,IntentService很像是一个后台线程,其实他是一个Service,正是因为他是服务所以不容易被系统杀死从而保证任务的正常进行.HandlerThread : 底层使用Thread 具有消息循环的线程, 内部可以使用Handler. 注意一 : 从Android 3.0 开始如果在子线程中进行网络操作就会产生NetworkOnMainThreadException代码中已经有了详细的注释,不进行过多解释,通过Log也证实了.这里说下取消任务
AsyncTask 提供了 cancel(boolean) 取消任务. 1. 参数含义:是否立即中断线程执行,true表示立即终止线程,false表示允许任务完成. 2. 调用了cancel() 后onCancelled() 回调会被执行(UI线程), onPostExecute() 不会被执行了. 3. 调用后 isCancelled 会返回 true. 4. 建议onInBackground() 中检查 isCancelled 以便尽快结束任务.
代码中已经有了详解的注释这里就不过多的解释了. 1. @MainThread 注解说明这两个方法都必须在主线程中执行,因此execute()方法必须在主线程中调用. 2. if (mStatus != Status.PENDING){...}中的判断说明了,一个AsyncTask对象只可以调用一次execute() 方法. 3. sDefaultExecutor是一个串行的线程池主要用于任务排队,并不负责任务的实际执行,源码分析如下
// sDefaultExecutor 定义 private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; // SERIAL_EXECUTOR : 用于任务排队. public static final Executor SERIAL_EXECUTOR = new SerialExecutor(); // SerialExecutor 串行线程池 private static class SerialExecutor implements Executor { final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); Runnable mActive; // 执行Runnable public synchronized void execute(final Runnable r) { mTasks.offer(new Runnable() { public void run() { try { r.run(); } finally { // 调度下一个. scheduleNext(); } } }); if (mActive == null) { scheduleNext(); } } // 启动下一个Runnable protected synchronized void scheduleNext() { if ((mActive = mTasks.poll()) != null) { // 执行任务. THREAD_POOL_EXECUTOR.execute(mActive); } } } // mFuture是一个Runnable private final FutureTask<Result> mFuture; THREAD_POOL_EXECUTOR 也是一个线程池,负责任务的执行. // 定义 public static final Executor THREAD_POOL_EXECUTOR; // 静态加载线程池. static { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); threadPoolExecutor.allowCoreThreadTimeOut(true); THREAD_POOL_EXECUTOR = threadPoolExecutor; } sHandler 负责线程环境的切换. // 7.0 代码 // 负责线程切换 private static InternalHandler sHandler; // 获取Handler private static Handler getHandler() { synchronized (AsyncTask.class) { if (sHandler == null) { sHandler = new InternalHandler(); } return sHandler; } } // 该类负责实现线程的切换 private static class InternalHandler extends Handler { // 7.0 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; } } } // 任务结束函数 private void finish(Result result) { if (isCancelled()) { // 任务被取消 onCancelled(result); } else { // 任务正常完成 onPostExecute(result); } mStatus = Status.FINISHED; }Android 5.0 代码
// 静态加载. private static final InternalHandler sHandler = new InternalHandler(); private static class InternalHandler extends Handler { @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对象,Android 6.0 以前,为了能够将执行环境切换到主线程,这就要求sHandler这个对象必须在主线程中进行创建.Android 6.0 以后 sHandler 使用了懒加载,因此,在子线程中也可以进行加载AsyncTask.同时在ActivityThread的main() 方法中也去掉了AsyncTask.init(); 也证实了这一点.HandlerThread 继承了Thread ,添加加了Looper, 实现方式如下: - 通过Looper.prepare() 来创建消息队列. - 通过Looper.loop() 来开启消息循环.
@Override public void run() { mTid = Process.myTid(); // 创建消息队列. Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); // 子类实现. onLooperPrepared(); // 开启运行循环. Looper.loop(); mTid = -1; } 普通的Thread主要用于进行耗时操作.HandlerThread内部常见了消息队列,外界需要通过Handler的消息方式通知HandlerThread来执行一个任务.由于HandlerThread的run() 是一个无限循环(Looper.loop()),因此当明确不需要时需要主动调用,quit() 或者 quitSafely() 来终止线程的执行.关于HandlerThread的使用方式参考IntentService源码
IntentService工作原理如下:
在onCreate() 中创建Handler和HandlerThread.并绑定.在onStart() 中通过Handler 发送消息.在 Handler中处理调用onHandleIntent()进行耗时操作.数据通过Intent进行传输.任务执行结束后,后停止服务.在onDestory() 中退出HandlerThread.运行代码发现上述三个任务串行执行,最后会停止服务.
Android线程池的概念源自于Java的Executor, Executor 是一个接口,ThreadPoolExecutor 是他的实现类.ThreadPoolExecutor提过了一系列的参数来配置线程池. Android中的线程池主要分为四类.后面会详细介绍.
除了上面的主要参数以外, ThreadPoolExecuteor还有一个不常用的参数RejectedExecutionHandler handler. 当线程池无法执行新的任务时会调用handler 的rejectedExeception方法来通知调用者, 默认情况下 rejectedExecution 方法会抛出一个rejectedExecutionException异常,具体的可以查看API文档.
ThreadPoolExecutor 执行时遵循以下规则:
如果线程池中的线程为达到核心线程的数量, 那么会直接启动一个核心线程来执行任务.如果线程池中的线程数量已经达到或者超过核心线程数量, 那么任务会插入任务队列中进行排队.如果过步骤2中无法将任务插入到任务队列,一般是队列已满,这个时候如果线程数量没有达到线程池的最大数量限制,那么会立即启动一个非核心线程来执行任务.如果步骤3中线程数量已经到了线程池规定的最大值, 那么就拒绝执行此任务,ThreadPoolExecutor会调用RejectedExecutionHandler的rejectedExecution() 方法来通知调用者.AsyncTask中的线程池配置
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; static { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); threadPoolExecutor.allowCoreThreadTimeOut(true); THREAD_POOL_EXECUTOR = threadPoolExecutor; }Android中常用有四种线程池,他们都是直接或者间接配置ThreadPoolExecutor 来实现自己的功能的.
newFixedThreadPool方法源码
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory); }newCachedThreadPool源码
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }newScheduledThreadPool源码
public static ScheduledExecutorService newScheduledThreadPool( int corePoolSize, ThreadFactory threadFactory) { return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory); }newSingleThreadExecutor源码
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }