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

相关推荐
刘龙超6 分钟前
如何应对 Android 面试官 -> 玩转 RxJava (基础使用)
android·rxjava
柿蒂1 小时前
从动态缩放自定义View,聊聊为什么不要把问题复杂化
android·ai编程·android jetpack
kerli1 小时前
kotlin协程系列:callbackFlow
android·kotlin
没有了遇见3 小时前
Android 原生定位实现(替代融合定位收费,获取经纬度方案)
android·kotlin
一枚小小程序员哈3 小时前
基于Android的车位预售预租APP/基于Android的车位租赁系统APP/基于Android的车位管理系统APP
android·spring boot·后端·struts·spring·java-ee·maven
用户2018792831673 小时前
pm path 和 dumpsys package 的区别
android
是店小二呀4 小时前
【C++】智能指针底层原理:引用计数与资源管理机制
android·java·c++
DoubleYellowIce5 小时前
一次混淆XLog导致的crash分析记录
android
你听得到115 小时前
弹窗库1.1.0版本发布!不止于统一,更是全面的体验升级!
android·前端·flutter