本篇重点介绍一下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接口的地方?
//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-400try {readAllPermissions();readPublicNativeLibrariesList();} finally {log.traceEnd();}}//....
}
这个案例直接传递了SystemConfig单例对象进去,此单例对象在构造函数中去做readAllPermissions文件处理,这是一个耗时任务,因此使用了子线程的方式。
2)prepareAppData
如上代码这里也没有传递一个Runnable接口,而是直接传递一个代码块,其中代码块用{}包裹,第二个参数传递prepareAppData,即任务描述,即第一个参数的代码块将在子线程中执行。
3)StartNativeSensorService
如上代码,启动native进程的服务,也通过了子线程的方式进行了启动,第二个参数直接把服务名传递了进去。
4、SystemServerInitThreadPool任务停止
如上日志表示SystemServerInitThreadPool调用shutdown进行终止所有线程池,我们来看看这段代码逻辑:
由此可见在开机完成之后,会主动调用SystemServerInitThreadPool.shutdown方法用来停止线程池中的所有任务,从上面的日志可以看出来,这些任务并不是直接暴力停止的,而是等待他们自己执行完成,具体实现如下:
PS:注意此段日志表示开机完成,非系统请求关机的日志