看到这个问题,让我回想起了曾经的自己。

我并不是搞后端开发的。在之前一段时间里,我在做Android开发的时候,曾重点做过线程相关的优化工作。

手机嘛,比不上服务器,CPU就那么大点。但当时的情况是,整个进程里头的线程池数量极多,甚至有的时候线程池的个数能比线程个数还多。这是个什么场景您就自己想吧。在这种情况下,我一开始是感觉很无力的。这么大点的一个APP,跑上百个线程,我的妈那叫一个头皮发麻。

这些线程池的来源非常复杂,有些是同事自己开的,有些是通过Executors创建的,还有些是直接调了项目里头曾经推广过的线程池创建接口,有些是RxJava还有Bolts等库里头的,还有一些是ThreadPoolExecutor的各种子类包括ScheduledThreadPoolExecutor,子类这种的最让人头疼。Timer还有HandlerThread还有野线程啥的就不提了,那些更麻烦。

线程池之间必然是会有影响的,线程多了它CPU切来切去的就是个成本,CPU就这么大,工作量就这么多,开了这么多线程它肯定要切换,除此之外线程一多它占用的内存也多,再然后这之间还互相会受影响。有些池设定得比预计得小了,结果那队列一排排一串,越排越长白占内存。还有些池它其实根本就没有多少任务要跑,有些业务有一定的串行需求或者定时需求,对于这种的线程池,池里面就没多少任务,但是任务既然投到这里头来了那还就得给分个线程,然后跑完了再接着让它在那park,这一来一回的要切上下文,切完了以后任务跑完了空闲在那里占着内存又得等半天才能超时销毁。再有些时候,有些线程池正等着释放一部分线程,同一时间另一部分线程池却收到了新任务然后又在那创建,结果这段时间里任务跑了多少不一定反正线程一会创建一会销毁倒是一直没闲着。

这个时候我就感觉要是全用Kotlin协程不就没这么多事了吗?但是没办法啊,协程也没少用可是已有的代码都有这么多了,再加上乱七八糟各种依赖库,自己的代码可以去整理出来去重构,第三方那可没法子改人家代码去。

我最后的处理方案是自己写一套线程池,让这些线程可以在各个池之间进行跨池复用。这样一来,甭管有多少线程池,甭管是串行还是定时还是不在乎配置啥参数就单纯地想要跑个异步的,我都能够把它限制在这部分线程里。

题主这个场景我觉得跟我当初那个差不多,只不过你是服务端我是客户端。我觉得最好的办法还是重构,当然了这是废话。你也可以参考一下我这个。先尽量定一套线程池的使用规则在组里推广,不能改的那就开个注入接口。自己写一套新的线程池库,然后改一趟字节码,这样的话对接入方基本是无感知的,不用侵入到同事的代码里,而且字节码插桩的方案也能让这部分逻辑覆盖到依赖库。不过手撸底层库和字节码毕竟的确还是挺有风险的。