线程优化
Anrdoid 中的线程模型
线程调度原理
- 任一时刻,一个
CPU
核心只有一个线程处于运行状态 - 多线程并发,轮流获取
CPU
使用权
线程调度模型
- 分时调度模型:轮流获取、均分
CPU
- 抢占式调度模型:谁抢到谁使用,优先级高的线程抢到的概率更高。所以最直接的干预就是设置线程优先级
Android 中采用抢占式调度模型
nice
值,【注意】nice值不是优先级Process 中定义,值越小优先级越高,默认时
THREAD_PRIORITY_DEFAUT = 0
1
Process.setThreadPriority()
priority
优先级线程优先级,值越大优先级越高
1
new Therad().setPriority()
cgroup
更严格的群组调度策略,如果低优先级的线程比较多而高优先级的线程较少,同样会造成高优先级线程饥饿,所以分前台
group
和后台group
,保证前台线程可以获取更多的CPU
时间片
注意事项
- 线程过多会导致
CPU
频繁切换,降低线程运行效率,还有可能出现线程饥饿(长时间没有得到执行) - 优先级具有继承性
- 正确认识任务重要性决定优先级
- 线程必须命名,以定位归属
- 注意区分
IO
密集型和CPU
密集型任务
Android 中异步的方式
- 直接创建
Thread
- 不易复用,频繁创建及销毁开销大
- 复杂场景不易使用,比如要执行一个定时的任务,能实现,但不易使用
HandlerThread
- 自带消息循环的线程,串行执行任务,适合长时间运行,不断从队列中获取任务
IntentService
- 继承自
Service
在内部创建HandlerThread
,异步不占用主线程 - 因为是
Service
所以优先级较高,不易被系统 Kill
- 继承自
AsyncTask
- Android 提供的异步工具类,内部的实现也是线程池
- 无需自己处理线程切换
- 线程池【推荐】
- 易复用,减少频繁创建、销毁的时间
- 功能强大:定时、任务队列、并发数控制等
RxJava
【推荐】- 完善的线程集合,区分
IO
、Computation
- 完善的线程集合,区分
线程使用准则
- 提供基础线程池供各个业务线使用
- 避免各自维护线程池,导致线程数过多
- 同时方便监控线程的调度情况
- 需要区分不同业务的异步方式,如
IO
、Computation
- CPU密集型线程池大小与CPU核心数相近
- 优先级低,长时间执行可以考虑使用
HandlerThread
- 定时任务,可以考虑使用线程池
- 创建线程必须命名
- 方便定位线程归属
- 运行期
Thread.currentThread().setName()
来修改名字,使用完后再修改回原理的名字
- 关键异步任务监控
- 重视优先级设置
Process.setThreadPriority()
- 可以设置多次
锁定线程创建者
项目变大之后,项目源码、三方库、aar
中都有创建线程,线程比较多,那就需要对线程进行收敛,那就需要知道线程是那里创建,是否足够合理。所有的异步方式,都会走到 new Thread
这个构造方法里,可以在这里获取调用栈的信息来锁定线程创建者
通过 Hook
Thread
的构造函数,来定位创建者,下面通过 ART-Hook
的方式来 Hook
构造函数
1 | DexposedBridge.hookAllConstructors(Thread.class, new XC_MethodHook() { |