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:注意此段日志表示开机完成,非系统请求关机的日志

相关推荐
Digitally18 小时前
如何用5种实用方法将电脑上的音乐传输到安卓手机
android·智能手机·电脑
HahaGiver66619 小时前
Unity与Android原生交互开发入门篇 - 打开Unity游戏的设置
android·unity·交互
2501_9159090619 小时前
WebView 调试工具全解析,解决“看不见的移动端问题”
android·ios·小程序·https·uni-app·iphone·webview
IT乐手20 小时前
android 下载管理工具类
android
2501_9151063221 小时前
App 怎么上架 iOS?从准备资料到开心上架(Appuploader)免 Mac 上传的完整实战流程指南
android·macos·ios·小程序·uni-app·iphone·webview
科技峰行者1 天前
安卓16提前发布能否改写移动生态格局
android
蒲公英少年带我飞1 天前
Android NDK 编译 protobuf
android
沐怡旸1 天前
【底层机制】ART虚拟机深度解析:Android运行时的架构革命
android·面试
小禾青青1 天前
uniapp安卓打包遇到报错:Uncaught SyntaxError: Invalid regular expression: /[\p{L}\p{N}]/
android·uni-app
studyForMokey1 天前
【Kotlin内联函数】
android·开发语言·kotlin