android hook 多线程,Android性能优化之线程优化

前言

线程在使用过程中,往往会遇见直接new Thread()的操作,这样做除了方便外,坏处也有很多,例如线程无法复用、线程数无法控制导致CPU频繁切换降低性能等问题。我们应当在项目早期就有意识的使用线程池收敛线程,降低后期的工作量。

1 线程调度

1.1 线程调度原理

任意时刻,只有一个线程占用CPU,处于运行状态

多线程并发:多个线程轮流获取CPU使用权

JVM负责线程调度:按照特定机制分配CPU使用权

1.2 线程调度模型

分时调度模型:轮流获取、均分CPU时间

抢占式调度模型:优先级高获取使用权,如果优先级都一样就随机选择线程执行。JVM使用此模型

1.3 Android线程调度

android为线程调度分别提供了设置nice值、cgroup两种方法。

nice值

Process中定义,值越小优先级越高。默认优先级是Process.THREAD_PRIORITY_DEFAULT

04ae2ac99643

Android线程优先级

cgroup

为了避免前、后台线程过多时相互影响对方执行,Android采取更严格的群组调度策略,保证前台线程可以获取到更多的CPU,但是又不会严重影响到后台线程的计算。

什么线程会被分配到后台线程?

优先级较低的线程、不在前台使用的线程会被移动到后台线程。

nice值和cgroup如何使用?

nice值和cgroup两个值,我们只能设置nice值

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)

-注意点

①线程过多会导致CPU频繁切换,降低线程运行效率。

②任务量大的线程应为较低优先级,避免产生①问题

③优先级具有继承性

2 Android异步

除了可以使用线程池外,Android还为我们提供了三种异步方法:HandlerThread、IntentService、AsyncTask。

2.1 Thread

最简单粗暴的方式,不建议直接使用,因为存在以下几点问题:

①不易复用,频繁创建及销毁开销大

②复杂场景不易使用,例如定时任务

2.2 HandlerThread

自带消息循环

①串行执行

②长时间运行,不断从队列中获取任务

2.3 IntentService

继承自Service在内部创建HnadlerThread

①异步,不占用主线程

②优先级较高,不易被系统kill

2.4 AsyncTask

Android提供异步工具类

①无需自己处理线程切换

②注意版本不一致

2.5 线程池

Java提供的线程池

①易复用,减少频繁创建、销毁的时间

②功能强大:定时、任务队列、并发数控制等

2.6 RxJava

由强大的Scheduler集合提供

①不同类型的区分:IO、Computation

3 Android线程优化

3.1 使用准则

严禁直接new Thread

提供基础线程池供各个业务线使用

①避免各个业务线各自维护一套线程池,导致线程数过多

根据任务类型选择合适的异步方式

①优先级低,长时间执行可以使用HandlerThread

创建线程必须命名

①方便定位线程归属

②运行期Thread.currentThread().setName修改名字。因为重命名容易被忽略,需要注意

关键异步任务监控

①异步不等于耗时

②AOP监控

重视优先级设置

①Process.setThreadPriority

3.2 线程池工具类

项目走向成熟期之后需要对线程进行收敛,避免线程随意创建,如果集成的框架能主动设置线程池,我们应当设置成自己的线程池,对线程创建及使用情况进行监控。

public class ThreadPoolUtils {

private final Executor mDiskExecutor;

private final Executor mNetworkExecutor;

private final Executor mMainThread;

private final ScheduledThreadPoolExecutor schedule;

//cpu密集型任务最大线程数

private int CPU_Runtime = Runtime.getRuntime().availableProcessors() + 1;

//io密集型任务最大线程数

private int IO_Runtime = Runtime.getRuntime().availableProcessors() * 2 + 1;

private static ThreadPoolUtils instance;

private static final Object object = new Object();

public static ThreadPoolUtils getInstance() {

if (instance == null) {

synchronized (object) {

if (instance == null) {

instance = new ThreadPoolUtils();

}

}

}

return instance;

}

private ThreadPoolUtils() {

this.mDiskExecutor = Executors.newFixedThreadPool(CPU_Runtime, new MyThreadFactory("MonsterDE"));

this.mNetworkExecutor = Executors.newFixedThreadPool(IO_Runtime, new MyThreadFactory("MonsterNE"));

this.mMainThread = new MainThreadExecutor();

this.schedule = new ScheduledThreadPoolExecutor(IO_Runtime, new MyThreadFactory("MonsterSC"),

new ThreadPoolExecutor.AbortPolicy());

}

/**

* 记录是线程池中第几个线程

*/

private static class MyThreadFactory implements ThreadFactory {

private final String name;

private final AtomicInteger mCount = new AtomicInteger(1);

MyThreadFactory(String name) {

this.name = name;

}

@Override

public Thread newThread(@NonNull Runnable r) {

return new Thread(r, name + "-" + mCount.getAndIncrement() + "-");

}

}

public Executor diskIO() {

return mDiskExecutor;

}

public ScheduledThreadPoolExecutor schedule() {

return schedule;

}

public Executor networkIO() {

return mNetworkExecutor;

}

public Executor mainThread() {

return mMainThread;

}

private static class MainThreadExecutor implements Executor {

private Handler mainThreadHandler = new Handler(Looper.getMainLooper());

@Override

public void execute(@NonNull Runnable command) {

mainThreadHandler.post(command);

}

}

}

4 锁定线程

为什么要锁定线程?

项目变大之后需要收敛线程,因为我们自身的项目源码、第三方库、aar文件都有可能存在线程的创建,我们需要通过监控预防去预防项目往不好的地方发展。

锁定线程创建方案

因为AAR可能混淆过,无法通过在new Thread中使用,但是我们可以在线下使用ARTHook方法,在线程构造函数打印调用堆栈。

总结

线程优化可以分为以下几点:

修改线程优先级(任务量大的可以降低优先级;但是一般不建议修改优先级,因为都想着自己线程的优先级更高的时候,线程优先级设置会变得无意义,深层次的原因是映射到系统线程等级问题,这里就不再展开说明)

选择合适的异步方法,例如Android提供的三种异步方法以及线程池,开发过程中可根据实际情况选择

使用线程池进行线程收敛,避免直接new Thread()

锁定线程,可通过ARTHook方案对线程进行监控,并打印线程堆栈信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值