Android的线程和线程池
主线程主要处理和界面相关的事情,子线程处理耗时的操作。
常见的除了Thread本身以外,还有asyncTask和IntentService,还有HandlerThread也是一种特殊的线程,asyncTask底层是线程池,IntentService和HandlerThread底层是线程实现的。
线程是操作系统调度的最小单元,所以它也是一种受限的系统资源,不可能无限产生,并且线程的创建和销毁都会有相应的开销。
11.1主线程和子线程
JAVA中默认一个进场只有一个线程,这个线程就是主线程,主要用于更新UI。
除了主线程外的线程都是子线程,子线程主要是做耗时操作。
11.2Android中的线程形态
asyncTask和IntentService,还有HandlerThread各有优缺点,下面分析一下各自优缺点。
11.2.1 asyncTask
asyncTask轻量级的异步任务类,可以在线程池中执行后台任务,然后把执行进度和最终结果传递给主线程并更新UI,具体使用参考最新API,下面是一些注意事项
1.asyncTask的对象必须在主线程中创建
2.execute方法必须在UI线程调用
3.不要在程序中直接调用onPreeExecute()等方法
4.一个asyncTask对象只能执行一次,也就是一次.execute方法
5.注意不同版本实现不太一样
11.2.2 asyncTask的工作原理
asyncTask实际上是一个串行的线程池,具体实现参考源码,实际上基本思路是封装了线程池和Handler对象,完成各个方法和回调的调用。
11.2.3 HandlerThread
HandlerThread继承了Thread,它是一种可以使用handler的Thread,主要是run方法中通过Looper.prepare()来创建消息队列,并且通过Looper.loop()来开启线程循环,这样实际运行中就可以创建handler了。
由于HandlerThread的run方法方法是无限循环的,不在使用HandlerThread的时候记得quit或者quitSafely退出执行。
11.2.4 IntentService
IntentService是一种特殊服务,IntentService是抽象类,必须创建它的子类才可以使用。IntentService也是封装了HandlerThread,因此适合后台播放音乐这种,长期后台服务,比线程优先级更高。
IntentService启动的时候,onCreate方法里面会创建HandlerThread,退出方法相对类似stopSelf(int startId)和stopSelf()结束,后者会直接退出,前者会安全退出。具体流程可以看AMS的stopServiceToken中找到相关代码。
IntentService会顺序执行后台任务,有多个任务执行的时候注意先后顺序,在执行完所有任务后,IntentService会真正的停止执行onDestroy(),服务正在停止。
11.3 Android中的线程池
线程池优点
1.复用线程池中的线程,避免反复创建销毁带来的性能开销
2.有效控制线程池的最大并发数,避免大量线程之间抢占系统资源导致阻塞现象。
3.能够对线程精细简单的管理,并提供定时执行和间隔循环执行等功能。
线程池概念来源Executor接口,真正实现类是ThreadPoolExecutor。具体API可以参考最新API
11.3.1 ThreadPoolExecutor
常见的构造方法参数解释
corePoolSize:核心线程数量,默认核心线程会一直存在,也可以指定超时时间,空闲超过这个时间就会被终止,需要allowCoreThreadTimeOut属性设置为true。
maximumPoolSize:线程池最大线程数量,超过会进入队列等待。
KeepAliveTime:非核心线程的闲置时的超时时长,超过这个时间就会被回收。
unit:用于KeepAliveTime参数的时间单位,毫秒、秒等
workQueue:线程池中的人物队列,通过线程池的execute方法提交的runnable对象会存储子啊这个对象
ThreadFactory:线程工厂,为线程池提供创建新的线程功能,这是一个接口,Thread NewThread(Runnable r)
ThreadPoolExecutor执行任务的大概规则
1.线程池线程数量未达到核心线程数量,那么会直接启动一个核心线程
2.线程池线程数量已经达到核心线程数量,那么会进入队列排队
3.如果队列已经满,那么会立即启动一个非核心线程来执行
4.如果步骤三的线程数量已经到达线程设置的最大值,那么会拒绝执行任务。
11.3.2 线程池的分类
有四种线程池:FixedThreadPool、CacheThreadPool、ScheduleThreadPool和SingleThreadExecute
1.FixedThreadPool
固定线程池,意味线程数量固定,除非线程池被回收,不然会一直运行,执行任务或者等待任务。
2.CacheThreadPool
缓冲线程池,线程数量不固定的,它只有非核心线程,超时机制一般是60S,没有任务的时候就是一个空集合。
3.ScheduleThreadPool
核心线程固定,非核心不固定,前面两个的结合体,非核心线程在没有使用的时候会立即回收。可以用来执行定时任务和具有固定周期的重复任务。
4.SingleThreadExecute
单一核心线程池,确认外界的任务在同一个线程中按照顺序执行。