前言
本插件内容是结合多家博客的精华改造而成的
插件地址:github.com/heyan224/la...
该插件主要是基于github.com/Knight-ZXW/... 的基础上细化改造的
目标
线程优化就是将自己代码中的线程以及各种sdk 中创建的线程都收敛到统一的线程池中,方便线程的管理。
我们知道创建线程的方式有多种:
new Threadnew ScheduledThreadPoolExecutornew ThreadPoolExecutornew FixedThreadPoolnew CachedThreadPoolExecutors.newSingleThreadExecutor()new HandlerThread
随着业务的膨胀以及接入各种三方sdk越来越多,那么在我们的apk中将存在大量无法管控的Thread实例以及 ThreadPoolExecutor 实例。
所以要达到线程收敛的目的就是要将 各种 new Thread 以及new ThreadPoolExecutor 等等实例都变成 一个 ,比如new ProxyThread、new PThreadPoolExecutor
以某一个sdk为例,线程收敛前某sdk的现状如下:

优化后:
我们已经将sdk中new Thread 以及new ThreadPoolExecutor 相关代码都改了
问题来了,即使都改成了new ProxyThread 、new PThreadPoolExecutor,这不是依然有很多线程和线程池的实例吗,依然没有达到收敛的目的?
确实,要想达到收敛的目的,还需要做一些事情,拿PThreadPoolExecutor 为例
我们在PThreadPoolExecutor 重写了ThreadPoolExecutor中的 execute 方法和 submit方法,当有人向线程池中提交任务时,我们这里并没有开启线程,而是通过 DefaultThreadPoolExecutor.getHCoreThreadPool ().execute(command) 将任务丢到了新的线程池中。 所以可以看出PThreadPoolExecutor 并不是真正的线程池,真正的线程池是 getHCoreThreadPool(),它是一个单例。
kotlin
public class PThreadPoolExecutor extends ThreadPoolExecutor {
//..........
//.........
@Override
public void execute(Runnable command) {
if (!SuperThreadPoolManager.isProxyThreadEnable()) {
super.execute(command);
return;
}
try {
DefaultThreadPoolExecutor.getHCoreThreadPool().execute(command);
} catch (OutOfMemoryError error) {
DefaultThreadPoolExecutor.getExtraThreadPool().execute(command);
}
}
@Override
public Future<?> submit(Runnable task) {
if (!SuperThreadPoolManager.isProxyThreadEnable()) {
return super.submit(task);
}
try {
return DefaultThreadPoolExecutor.getHCoreThreadPool().submit(task);
} catch (OutOfMemoryError error) {
return DefaultThreadPoolExecutor.getExtraThreadPool().submit(task);
}
}
@Override
public <T> Future<T> submit(Callable<T> task) {
if (!SuperThreadPoolManager.isProxyThreadEnable()) {
return super.submit(task);
}
try {
return DefaultThreadPoolExecutor.getHCoreThreadPool().submit(task);
} catch (OutOfMemoryError error) {
return DefaultThreadPoolExecutor.getExtraThreadPool().submit(task);
}
}
}
使用
- 项目的根目录下的
build.gradle中添加
classpath 'io.github.heyan224:lancet-plugin:0.0.6'
- app目录下的
build.gradle中添加
implementation 'io.github.heyan224:lancet-runtime:0.0.2'
- 还是在 app目录下的
build.gradle中添加如下的配置
bash
apply plugin: 'LancetX'
LancetX{
enable true
enableInDebug true
weaveGroup {
threadOptimize {
enable false
whiteNames = [
"com/bb",
"com/aa",
"com/xx"
]
blackNames = [
]
}
}
}
这里解释几个关键的字段:
arduino
threadOptimize { // 线程优化配置项
enable true // 开关
whiteNames = [ // 白名单,我们可以添加白名单,来指定特定的几个sdk来进行线程优化
"com/bb",
"com/aa",
"com/xx"
]
blackNames = [ // 黑名单
]
}
- 最后一步就是来实现 我们自己的
ProxyThreadPThreadPoolExecutor代码了,以及Thread和ProxyThread的映射,ThreadPoolExecutor和PThreadPoolExecutor的映射
也就是我们要告诉字节码修改插件,我们想要修改哪些类,比如我们将要修改 Thread 类,修改为 ProxyThread,代码如下图。
另外 ProxyThread 、PThreadPoolExecutor、getHCoreThreadPool()的实现都已在仓库中了
注意点
线程收敛到这里其实还没开始,因为真正重要的是我们的代理线程池的参数应该如何配置。
我们都知道线程池有几个重要的参数需要深思熟虑
- 线程池核心线程数
- 线程池最大线程数
- 任务等待队列
- 线程空闲多久要回收,也就是keepAliveTime
- 线程任务拒绝策略的制定 RejectedExecutionHandler
这几个参数的制定对于线程收敛很重要。