Android SystemServer 系列专题【篇四:SystemServerInitThreadPool线程池管理】

本篇重点介绍一下SystemServerInitThreadPool,顾名思义此类针对SystemServer进程的提供了一套ThreadPool线程池的统一标准方案,下面从源码和日志的角度来剖析一个这个类。

1、SystemServerInitThreadPool单例设计

SystemServerInitThreadPool的源码路径在frameworks/base/services/core/java/com/android/server,如下代码其构造方法被定义为private,且存在静态类sInstance,这是一种典型的单例设计模式。

那么为什么这里采用了单例的设计模式呢?从后文可以看出来SystemServer的各个子服务都会通过这个类来执行耗时任务,因此单例设计是最优选,并且对sInstance进行了加锁保证线程安全。

2、SystemServerInitThreadPool何时启动?

第一节介绍了构造方法被private修饰,那么何时被构造何时被启动呢?

接下来继续看看start方法,该方法被定义为static方法,方法内通过LOCK去进行实例化,因此是一个典型的单例模式。

那么何时调用start方法呢?如下代码在SystemServer进程的主流程中,并且放到了startxxx之前,为什么要放在这里呢?因为后续的三部曲都需要使用该类去执行一些子线程的任务。

我们来看一下SystemServerInitThreadPool启动日志:可以看出来线程池的长度为8

3、SystemServerInitThreadPool任务执行

继续看一下submit方法,改方法为静态方法,供其他XXXService进行调用,最后移交给submitTask方法来创建启动线程池。这里的mService就是构造方法中通过mSize创建的线程池。

接下来看看在开机过程中,有哪些服务在调用这个方法创建子任务呢?

下面举几个submit的示例:

1)ReadingSystemConfig

这里很奇怪的是第一个参数应该是Runnable接口,第二个参数是字符串用来进行描述,但是这里的第一个参数直接返回了SystemConfig的实例,且该类没有找到实现Runnable接口的地方?

java 复制代码
//frameworks/base/core/java/com/android/server/SystemConfig.java 
public class SystemConfig {
    static final String TAG = "SystemConfig";
    static SystemConfig sInstance;
    public static SystemConfig getInstance() {
        if (!isSystemProcess()) {
            Slog.wtf(TAG, "SystemConfig is being accessed by a process other than " + "system_server.");
        }
        synchronized (SystemConfig.class) {
            if (sInstance == null) {
                sInstance = new SystemConfig();
            }
            return sInstance;
        }
    }
    SystemConfig() {
        TimingsTraceLog log = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
        log.traceBegin("readAllPermissions");
        TDSystemConfig.getInstance();// TINNO modified by guobing.xiong 20230208 LIBRA-400
        try {
            readAllPermissions();
            readPublicNativeLibrariesList();
        } finally {
            log.traceEnd();
        }
    }
    //....
}

这个案例直接传递了SystemConfig单例对象进去,此单例对象在构造函数中去做readAllPermissions文件处理,这是一个耗时任务,因此使用了子线程的方式。

2)prepareAppData

如上代码这里也没有传递一个Runnable接口,而是直接传递一个代码块,其中代码块用{}包裹,第二个参数传递prepareAppData,即任务描述,即第一个参数的代码块将在子线程中执行。

3)StartNativeSensorService

如上代码,启动native进程的服务,也通过了子线程的方式进行了启动,第二个参数直接把服务名传递了进去。

4、SystemServerInitThreadPool任务停止

如上日志表示SystemServerInitThreadPool调用shutdown进行终止所有线程池,我们来看看这段代码逻辑:

由此可见在开机完成之后,会主动调用SystemServerInitThreadPool.shutdown方法用来停止线程池中的所有任务,从上面的日志可以看出来,这些任务并不是直接暴力停止的,而是等待他们自己执行完成,具体实现如下:

PS:注意此段日志表示开机完成,非系统请求关机的日志

相关推荐
AI_Gump3 小时前
Harness篇|DeepSeek Harness 上手机:五条安卓移植路线与 App 内 Linux 拆解
android·linux·人工智能·智能手机·deepseek
疯华整猫8 小时前
否决 Flutter 提案那天,我发现自己也说不清 Framework 管什么
android
传奇开心果编程20 小时前
【Flutter踩坑排雷】第25课:ScrollController 误用坑|跳转失效、监听泄漏与“控制器未附加”
android·flutter·ios·移动开发·跨平台·dart·声明式ui
慕容雪_1 天前
Capacitor8-Android打包完整手册
android·打包·capacitor
阿杰m1 天前
Android源码第十三章:Bluetooth——沿一次发现走到控制器
android
booboosui1 天前
派活给另一个 AI:前后两次文件夹快照,就是交付清单
android
普通人61 天前
MySQL_FIND_IN_SET函数详解
android·数据库·mysql
好的佩奇2 天前
Dart 之集合元素
android·flutter·dart
Easyhood2 天前
Android 开发入门实践(十四):Compose 副作用入门与四个常用 API
android·开发语言·kotlin·android jetpack·compose
FlightYe2 天前
音视频修炼之容器与协议(四):RTSP详解
android·linux·ffmpeg·音视频·dash