大家对多线程处理耗时工作的重要性应该早已认识到。本章的关键点是:把耗时的、与UI渲染无关的操作进行分割分配到多个线程中并发执行。
在本章,googler 全篇介绍了通过 java 线程池来构造多线程执行环境的详细流程,关键要点如下:
1. 定义一个能在 Thread 中执行的 Runnable 子类 SubRunnable,把耗时的工作交给 SubRunnable 的 run() 方法;
2. 在 run() 中通过 Thread.currentThread() 获取并保存SubRunnable 所在的线程以备中断所需;
3. 初始化一个 BlockingQueue<Runnable> 队列的实例runQueue,用于排队缓冲等待执行的 SubRunnables;
4. 初始化并配置一个 java 线程池 ThreadPoolExecutor的实例 threadpool,配置初始化可用线程数、最大可用线程数、线程关闭前的闲置时间、闲置时间单位、工作队列(即上述初始化的 runQueue);
5. threadpool 是 runQueue 的实际操纵者,负责将 SubRunnable 排队、按照FIFO策略给 SubRunnable 分配 Thread 并调度执行;
6. 构造一个 Handler 的实例 mainHandler 用于接收 SubRunnable 执行的状态和结果,并更新UI,所以必须用主线程Looper 来初始化它:mainHandler= new Handler(Looper.getMainLooper()); 这样 mainHandler 将与 mian Looper 同处于主线程中,可以接收主线程的派发事件;
7. 当需要提交新的任务执行时,调用 threadpool.execute(newRunnable); newRunnable 将被排队调度执行;
8. 当 SubRunnable 需要报告执行状态和结果时,通过 mainHandler 传送给 UI 线程处理;
9. 当 SubRunnable 执行完毕,确定不再需要它时,中断其所在线程,并将其从队列中移除:”the runnable’s thread”.interrupt(); threadpool.remove(“the runnable”);这点很重要,否则队列中的资源无法释放,严重时将抛出 RejectedExecutionHandler 异常。
实际上这是一个android.os.AsyncTask 的手动实现流程,android.os.AsyncTask 正是对此流程的一种封装,只是不过手动实现的方案有更大的弹性,你可以灵活地配置 ThreadPoolExecutor 的参数和队列。
如果大家有兴趣可以查看一下android.os.AsyncTask 的源代码:
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.2.2_r1/android/os/AsyncTask.java#AsyncTask
下面通过图示简要总结一下以上流程: