线程优化

2021-03-24  本文已影响0人  flynnny

1Android线程调度原理剖析

线程调度原理

任意时刻,只有一个线程占用CPU,处于运行状态。
多线程并发:轮流获取CPU使用权
JVM负责线程调度:按照特定机制分配CPU使用权

线程调度模型
分时调度模型:轮流获取、均分时间片
抢占式调度模型:优先级高的获取,JVM采用(一样则随机一个)

Android线程调度

nice值:

1Process中定义
2值越小,优先级越高
3默认值是THREAD_PRIORITY_DEFAULT,0

1.png 2.png

并不足够。

cgroup

1更严格的群组调度策略
2保证前台线程可以获取更多的CPU

哪些线程会移到后台group?
手动设置优先级低的线程;不在前台运行的线程

3.png

没指定线程优先级,默认继承:比如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
可以直接使用这个全局统一的线程池

5.png

修改下线程加个名字

6.png

每个线程都叫这个不好,可以从1-5排开,在使用处修改

8.png

线程优先级设置

9.png

使用阶段也可以修改优先级

10.png

4如何锁定线程创建者

锁定线程创建者背景

项目变大之后收敛线程
我们的项目源码、三方库、aar中都有线程创建
避免恶化的一种监控预防手段

锁定线程创建者方案

11.png

特别适合Hook手段
找Hook点:构造函数或者特定方法
Thread的构造函数

实战

在attachBaseContext中进行hook:

12.png 13.png 14.png

5线程收敛优雅实现

常规方案

15.png

基础库怎么使用线程?
直接依赖线程库
缺点:线程库更新可能会导致基础库更新

优雅方式

基础库内部暴露API:setExecutor
初始化时注入统一线程库

实战

16.png

完成。

17.png

IO密集型任务,核心池可以很大(比如网络请求)
CPU密集型任务:核心池大小要和CPU相关

6模拟面试

线程使用为什么会遇到问题?
早期没有采用统一线程池,乱多--》卡顿、耗时
java是抢占式的要区分,针对IO密集型任务,CPU密集型任务也要区分。很可能出现主线程抢不到时间片情况

怎么优化线程?
划分层次,不讲太多细节
数量多--》线程收敛,采用hook查看堆栈信息,是不是应该被单独创建。基础库暴露接口,注入库
任务区分,不消耗CPU的任务,核心线程数可以大一些
重要异步逻辑监控,监控时间、线程名。

上一篇下一篇

猜你喜欢

热点阅读