1Android线程调度原理剖析
线程调度原理
任意时刻,只有一个线程占用CPU,处于运行状态。
多线程并发:轮流获取CPU使用权
JVM负责线程调度:按照特定机制分配CPU使用权
线程调度模型
分时调度模型:轮流获取、均分时间片
抢占式调度模型:优先级高的获取,JVM采用(一样则随机一个)
Android线程调度
nice值:
1Process中定义
2值越小,优先级越高
3默认值是THREAD_PRIORITY_DEFAULT,0
并不足够。
cgroup
1更严格的群组调度策略
2保证前台线程可以获取更多的CPU
哪些线程会移到后台group?
手动设置优先级低的线程;不在前台运行的线程
没指定线程优先级,默认继承:比如UI线程中创建的线程继承了UI线程的优先级。会抢占
2Android异步方式汇总(从上到下推荐)
Thread
最简单,最常见的异步
不宜复用,频繁创建及销毁开销大
复杂场景不适用
HandlerThread
也是一个Thread
自带消息循环的线程
串行执行
适合长时间运行,不断从队列中取出任务的场景
IntentService
继承自Service在内部创建HandlerThread
1异步,不占用主线程
2优先级较高,不容易被Kill
AsyncTask
Android 提供的工具类
1无需自己处理线程切换
2注意版本不一致问题(比较容易被问,现在14+后没有了)
线程池
java提供的线程池
1易复用,减少频繁创建、销毁时间
2功能强大:定时、任务队列、并发数控制
Rxjava
由强大的Scheduler集合提供
不同的类型区分:IO、Computation
如果集成了Rxjava,推荐使用这个
3Android线程优化实战
线程使用准则
1严禁直接 new Thread
2提供一个基础线程池供各个业务线使用
.避免各个业务线各自维护一套线程池,导致线程数过多
3根据任务类型选择合适的异步方式
.优先级低,长时间执行--》HandlerThread
.需要定时执行---》线程池
4创建线程必须命名
.方便定位线程归属
.运行期Thread.currentThread().setName修改名字
5关键的异步任务监控
.异步不等于不耗时
6重视优先级设置
Process.setThreadPriority();
可以设置多次。
线程设置优先级实战
4.png核心线程数5
可以直接使用这个全局统一的线程池
修改下线程加个名字
6.png每个线程都叫这个不好,可以从1-5排开,在使用处修改
8.png线程优先级设置
9.png使用阶段也可以修改优先级
10.png4如何锁定线程创建者
锁定线程创建者背景
项目变大之后收敛线程
我们的项目源码、三方库、aar中都有线程创建
避免恶化的一种监控预防手段
锁定线程创建者方案
11.png特别适合Hook手段
找Hook点:构造函数或者特定方法
Thread的构造函数
实战
在attachBaseContext中进行hook:
12.png 13.png 14.png5线程收敛优雅实现
常规方案
15.png基础库怎么使用线程?
直接依赖线程库
缺点:线程库更新可能会导致基础库更新
优雅方式
基础库内部暴露API:setExecutor
初始化时注入统一线程库
实战
16.png完成。
17.pngIO密集型任务,核心池可以很大(比如网络请求)
CPU密集型任务:核心池大小要和CPU相关
6模拟面试
线程使用为什么会遇到问题?
早期没有采用统一线程池,乱多--》卡顿、耗时
java是抢占式的要区分,针对IO密集型任务,CPU密集型任务也要区分。很可能出现主线程抢不到时间片情况
怎么优化线程?
划分层次,不讲太多细节
数量多--》线程收敛,采用hook查看堆栈信息,是不是应该被单独创建。基础库暴露接口,注入库
任务区分,不消耗CPU的任务,核心线程数可以大一些
重要异步逻辑监控,监控时间、线程名。
网友评论