当前位置: 首页 > news >正文

SystemServer 进程启动过程

首语

SystemServer进程主要用于启动系统服务,诸如AMS、WMS、PMS都是由它来创建的。在系统的名称为"system_server",Android核心服务都是它启动,它是非常重要。

Zygote处理SystemServer进程

在 Zygote启动过程 文章中分析我们知道,调用Zygote的forkSystemServer方法启动SystemServer进程。

调用nativeZygoteInit方法,它是Native层的代码,用来启动Binder线程池,这样SystemServer进程就可以使用Binder与其它进程进行通信。

调用applicationInit方法,通过反射得到SystemServer类,className为com.android.server.SystemServer,然后找到SystemServer类 的main方法。传入MethodAndArgsCaller类并返回给ZygoteInit类的main方法。调用MethodAndArgsCaller类的run方法,MethodAndArgsCaller类是RuntimeInit类的静态类。最后动态调用SystemServer的main方法。

源码路径:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

private static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) {...if (pid == 0) {if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName);}zygoteServer.closeServerSocket();//处理SystemServer进程return handleSystemServerProcess(parsedArgs);}
}
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {...ClassLoader cl = getOrCreateSystemServerClassLoader();if (cl != null) {Thread.currentThread().setContextClassLoader(cl);}//Pass the remaining arguments to SystemServer.return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mDisabledCompatChanges,parsedArgs.mRemainingArgs, cl);    
}public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,String[] argv, ClassLoader classLoader) {if (RuntimeInit.DEBUG) {Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");}Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");RuntimeInit.redirectLogStreams();RuntimeInit.commonInit();//启动Binder线程池ZygoteInit.nativeZygoteInit();//进入SystemServer的main方法return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,classLoader);
}
public static void main(String[] argv) {...if (startSystemServer) {Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);// {@code r == null} in the parent (zygote) process, and {@code r != null} in the// child (system_server) process.//MethodAndArgsCaller.run方法if (r != null) {r.run();return;}}  
}

源码路径:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,String[] argv, ClassLoader classLoader) {...// Remaining arguments are passed to the start class's static mainreturn findStaticMain(args.startClass, args.startArgs, classLoader);
}
protected static Runnable findStaticMain(String className, String[] argv,ClassLoader classLoader) {Class<?> cl;try {//反射得到SystemServer类cl = Class.forName(className, true, classLoader);} catch (ClassNotFoundException ex) {throw new RuntimeException("Missing class when invoking static main " + className,ex);}Method m;try {//知道main方法m = cl.getMethod("main", new Class[] { String[].class });} catch (NoSuchMethodException ex) {throw new RuntimeException("Missing static main on " + className, ex);} catch (SecurityException ex) {throw new RuntimeException("Problem getting static main on " + className, ex);}int modifiers = m.getModifiers();if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {throw new RuntimeException("Main method is not public and static on " + className);}/** This throw gets caught in ZygoteInit.main(), which responds* by invoking the exception's run() method. This arrangement* clears up all the stack frames that were required in setting* up the process.*/return new MethodAndArgsCaller(m, argv);
}
static class MethodAndArgsCaller implements Runnable {/** method to call */private final Method mMethod;/** argument array */private final String[] mArgs;public MethodAndArgsCaller(Method method, String[] args) {mMethod = method;mArgs = args;}public void run() {try {//动态调用SystemServer的main方法mMethod.invoke(null, new Object[] { mArgs });} catch (IllegalAccessException ex) {throw new RuntimeException(ex);} catch (InvocationTargetException ex) {Throwable cause = ex.getCause();if (cause instanceof RuntimeException) {throw (RuntimeException) cause;} else if (cause instanceof Error) {throw (Error) cause;}throw new RuntimeException(ex);}}
}

解析SystemServer进程

main方法调用了SystemServer的run方法,在run方法里,首先进行了一些系统属性的设置、加载动态库及创建系统的Context。然后创建了SystemServiceManager,它会对系统服务进行创建、管理和生命周期管理。接下来有四个关键方法。

  • startBootstrapServices(t)。启动引导服务。共启动了约25个引导服务。例如我们熟知的AMS、PMS等服务。其中主要创建引导服务及作用如下(所有服务查看对应方法):
引导服务作用
Installer系统安装APK时候的一个服务类,启用完成Installer服务后才能启动其它的系统服务
ActivityManagerService负责四大组件的启动、切换、调度
PowerManagerServiceAndroid系统中和Power相关的计算,决策系统电影策略
LightService管理和显示背光LED
DisplayManagerService管理所有显示设备
PackageManagerService对APK进行安装、解析、验签、卸载等操作
UserManagerService多用户模式管理服务
SensorServiceAndroid各种感应器服务
  • startCoreServices(t)。启动核心服务。共启动了约11个核心服务。主要核心服务及作用如下(所有服务查看对应方法):
核心服务作用
BatteryService管理电池相关服务
UsageStatsService收集用户使用App的频率、使用时长
WebViewUpdateServiceWebview更新服务
BugreportManagerServicebugreport的管理服务
GpuService管理GPU资源的服务
  • startOtherServices(t)。启动其它服务。它启动了多达几十种服务。大多是我们使用设备功能息息相关的服务。主要其它服务及作用如下(所有服务查看对应方法):
其它服务作用
AlarmManagerService定时器管理服务
InputManagerService输入事件管理服务
CameraServiceProxy摄像相关服务
WindowManagerService窗口管理服务
VrManagerServiceVR模式管理服务
BluetoothService蓝牙管理服务
NotificationManagerService通知管理服务
StorageManagerService存储管理服务
LocationManagerService定位管理服务
AudioService音频管理服务

在这个方法里,可以看到服务启动的多个阶段标志,如PHASE_SYSTEM_SERVICES_READY/PHASE_DEVICE_SPECIFIC_SERVICES_READY等。其中PHASE_BOOT_COMPLETED=1000;标志着完成了Android开机启动流程。系统服务更倾向于监听该阶段,而不是注册广播BOOT_COMPLETED,从而降低系统延迟。

  • startApexServices(t)。启动Apex服务。

Apex服务是指Android操作系统中的一种应用程序启动方式,它允许应用程序在设备启动时以系统服务的形式自动运行。这些服务通常包括系统应用、框架服务和系统UI等。它们在设备启动时会自动运行,并为用户提供各种基础功能和界面。

startApexServices方法会遍历所有已安装的Apex服务,并调用它们的启动方法,使它们在系统启动时自动运行。该方法在系统启动过程中被调用,是Android操作系统启动过程中的一部分。

从这里我们也能看出来,官方将系统服务分为了以上四种。它们启动方法相似。通过SystemServiceManager类的startService方法启动。我们以PowerManagerService为例进行分析如何启动。

startService中调用PowerManagerService类的onStart方法完成启动PowerManagerService。

除了通过SystemServiceManager类的startService方法启动外,还有通过对应Service的main方法启动,例如PackageManagerService。

由源码可知,PackageManagerService被注册到ServiceManager中。ServiceManager用来管理系统的各种Service,这些服务通过Binder通信机制与应用程序进行通信。

源码路径:frameworks/base/services/java/com/android/server/SystemServer.java

public static void main(String[] args) {new SystemServer().run();
}
private void run() {TimingsTraceAndSlog t = new TimingsTraceAndSlog();try {...//创建消息LooperLooper.prepareMainLooper();Looper.getMainLooper().setSlowLogThresholdMs(SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);SystemServiceRegistry.sEnableServiceNotFoundWtf = true;// 加载动态库libandroid_servers.soSystem.loadLibrary("android_servers");// Allow heap / perf profiling.initZygoteChildHeapProfiling();// Debug builds - spawn a thread to monitor for fd leaks.if (Build.IS_DEBUGGABLE) {spawnFdLeakCheckThread();}// Check whether we failed to shut down last time we tried.// This call may not return.performPendingShutdown();// 创建系统ContextcreateSystemContext();// Call per-process mainline module initialization.ActivityThread.initializeMainlineModules();// Sets the dumper serviceServiceManager.addService("system_server_dumper", mDumper);mDumper.addDumpable(this);// 创建SystemServiceManager,对系统服务进行创建、启动和生命周期管理mSystemServiceManager = new SystemServiceManager(mSystemContext);mSystemServiceManager.setStartInfo(mRuntimeRestart,mRuntimeStartElapsedTime, mRuntimeStartUptime);mDumper.addDumpable(mSystemServiceManager);LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);// Prepare the thread pool for init tasks that can be parallelizedSystemServerInitThreadPool tp = SystemServerInitThreadPool.start();mDumper.addDumpable(tp);...} finally {t.traceEnd();  // InitBeforeStartServices}// Setup the default WTF handlerRuntimeInit.setDefaultApplicationWtfHandler(SystemServer::handleEarlySystemWtf);// Start services.try {t.traceBegin("StartServices");//启动引导服务startBootstrapServices(t);//启动核心服务startCoreServices(t);//启动其它服务startOtherServices(t);//启动Apex服务startApexServices(t);} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;} finally {t.traceEnd(); // StartServices}...}
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {...//启动AMS,ActivityTaskManagerService->ActivityManagerServicet.traceBegin("StartActivityManager");ActivityTaskManagerService atm = mSystemServiceManager.startService(ActivityTaskManagerService.Lifecycle.class).getService();mActivityManagerService = ActivityManagerService.Lifecycle.startService(mSystemServiceManager, atm);mActivityManagerService.setSystemServiceManager(mSystemServiceManager);mActivityManagerService.setInstaller(installer);mWindowManagerGlobalLock = atm.getGlobalLock();t.traceEnd();t.traceBegin("StartPowerManager");mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);t.traceEnd();t.traceBegin("StartPackageManagerService");try {Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");Pair<PackageManagerService, IPackageManager> pmsPair = PackageManagerService.main(mSystemContext, installer, domainVerificationService,mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);mPackageManagerService = pmsPair.first;iPackageManager = pmsPair.second;} finally {Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");}...mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);...
}
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {...// WMS needs sensor service readymSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE);...mSystemServiceManager.startBootPhase(t, SystemService.PHASE_LOCK_SETTINGS_READY);...mSystemServiceManager.startBootPhase(t, SystemService.PHASE_SYSTEM_SERVICES_READY);...mSystemServiceManager.startBootPhase(t, SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);...mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY);...mSystemServiceManager.startBootPhase(t, SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);}
private void startApexServices(@NonNull TimingsTraceAndSlog t) {List<ApexSystemServiceInfo> services = ApexManager.getInstance().getApexSystemServices();for (ApexSystemServiceInfo info : services) {String name = info.getName();String jarPath = info.getJarPath();t.traceBegin("starting " + name);if (TextUtils.isEmpty(jarPath)) {mSystemServiceManager.startService(name);} else {mSystemServiceManager.startServiceFromJar(name, jarPath);}t.traceEnd();}
}

源码路径:frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

public void startService(@NonNull final SystemService service) {// Check if already startedString className = service.getClass().getName();if (mServiceClassnames.contains(className)) {Slog.i(TAG, "Not starting an already started service " + className);return;}mServiceClassnames.add(className);// Register it.mServices.add(service);// Start it.long time = SystemClock.elapsedRealtime();try {//启动serviceservice.onStart();} catch (RuntimeException ex) {throw new RuntimeException("Failed to start service " + service.getClass().getName()+ ": onStart threw an exception", ex);}warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
}
//系统服务启动指定的启动阶段
public void startBootPhase(@NonNull TimingsTraceAndSlog t, int phase) {if (phase <= mCurrentPhase) {throw new IllegalArgumentException("Next phase must be larger than previous");}mCurrentPhase = phase;Slog.i(TAG, "Starting phase " + mCurrentPhase);try {t.traceBegin("OnBootPhase_" + phase);final int serviceLen = mServices.size();for (int i = 0; i < serviceLen; i++) {final SystemService service = mServices.get(i);long time = SystemClock.elapsedRealtime();t.traceBegin("OnBootPhase_" + phase + "_" + service.getClass().getName());try {//系统服务的onBootPhase方法service.onBootPhase(mCurrentPhase);} catch (Exception ex) {throw new RuntimeException("Failed to boot service "+ service.getClass().getName()+ ": onBootPhase threw an exception during phase "+ mCurrentPhase, ex);}warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onBootPhase");t.traceEnd();}} finally {t.traceEnd();}//开机阶段if (phase == SystemService.PHASE_BOOT_COMPLETED) {final long totalBootTime = SystemClock.uptimeMillis() - mRuntimeStartUptime;t.logDuration("TotalBootTime", totalBootTime);SystemServerInitThreadPool.shutdown();}
}
public boolean isBootCompleted() {return mCurrentPhase >= SystemService.PHASE_BOOT_COMPLETED;
}

源码路径:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public static Pair<PackageManagerService, IPackageManager> main(Context context,Installer installer, @NonNull DomainVerificationService domainVerificationService,boolean factoryTest, boolean onlyCore) {...PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest,PackagePartitions.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG,Build.VERSION.SDK_INT, Build.VERSION.INCREMENTAL);...IPackageManagerImpl iPackageManager = m.new IPackageManagerImpl();ServiceManager.addService("package", iPackageManager);...
}

SystemServer在启动系统服务存在多个阶段,如下所示:
源码路径:frameworks/base/services/core/java/com/android/server/SystemService.java

    /*** 系统在引导时向系统服务发送的最早引导阶段。*/public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100;/*** 在SensorService可用性上阻塞的引导阶段。该服务是异步启动的,因为它可能需要一段时间才能完成初始化。* @hide*/public static final int PHASE_WAIT_FOR_SENSOR_SERVICE = 200;/*** 在接收这个启动阶段后,服务可以获取锁设置数据。*/public static final int PHASE_LOCK_SETTINGS_READY = 480;/*** 在收到此启动阶段后,服务可以安全地调用核心系统服务*/public static final int PHASE_SYSTEM_SERVICES_READY = 500;/*** 在收到此启动阶段后,服务可以安全地调用设备特定的服务。*/public static final int PHASE_DEVICE_SPECIFIC_SERVICES_READY = 520;/*** 在收到此启动阶段后,服务可以广播意图。*/public static final int PHASE_ACTIVITY_MANAGER_READY = 550;/*** 在收到此启动阶段后,服务可以启动/绑定到第三方应用程序。应用程序将能够在此处对服务进行 Binder 调用。*/public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;/*** 在收到此启动阶段后,服务允许用户与设备进行交互。此阶段发生在启动完成且主应用程序已启动时。系统服务可能更倾向于监听此阶	   * 段,而不是注册ACTION_LOCKED_BOOT_COMPLETED减少整体延迟。*/public static final int PHASE_BOOT_COMPLETED = 1000;

总结

Zygote调用startSystemServer创建SystemServer进程。SystemServer进程启动了各种系统服务(四种),并且SystemServer在启动系统服务有定义多个阶段。SystemServiceManager对系统服务进行管理。

相关文章:

SystemServer 进程启动过程

首语 SystemServer进程主要用于启动系统服务&#xff0c;诸如AMS、WMS、PMS都是由它来创建的。在系统的名称为"system_server"&#xff0c;Android核心服务都是它启动&#xff0c;它是非常重要。 Zygote处理SystemServer进程 在 Zygote启动过程 文章中分析我们知道…...

Java EE 多线程之 JUC

文章目录 1. Callable 接口2. ReentrantLock3. 信号量4. CountDownLatch JUC这里就是指&#xff08;java.util.concurrent&#xff09; concurrent 就是并发的意思 这个包里的内容&#xff0c;主要就是一些多线程相关的组件 1. Callable 接口 Callable 也是一种创建线程的方式…...

Unity光照模型实践

光照作为3D渲染中最重要的部分之一&#xff0c;如何去模拟真实环境的光照是重要的研究内容&#xff0c;但是现实环境光照过于复杂&#xff0c;有很多经典好用的光照模型去近似真实光照。 根据基础的Phong模型 最终某个点的结果为 环境光Ambient 漫反射光Diffuse 高光Specula…...

从0创建并部署一个网页到服务器

创建一个页面 1 下载node.js 下载VScode 2 在Windows下找一个路径新建一个文件夹 例如&#xff1a;D:\study_project\PersonalWeb 3 VSCodee中打开文件夹 4 Windows下 管理员身份打开命令提示符&#xff0c;执行npm install -g vue/cli 5 VSCode下打开终端&#xff0c;执…...

Ubuntu 22.04 安装 OCI CLI

Ubuntu 22.04 安装 OCI CLI 安装命令 安装命令 wget https://codeload.github.com/oracle/oci-cli/zip/master -O oci-cli.zip pip install oci-cli.zip完结&#xff01;...

K8S的安装工具

kubectl Kubernetes 命令行工具 kubectl&#xff0c; 让你可以对 Kubernetes 集群运行命令。 你可以使用 kubectl 来部署应用、监测和管理集群资源以及查看日志。 有关更多信息&#xff0c;包括 kubectl 操作的完整列表&#xff0c;请参见 kubectl参考文件。 kubectl 可安装在…...

vue中哪些数组的方法可以做到响应式

Vue2 中为什么直接通过数组的索引修改元素是不会触发视图更新 vue2 为什么不直接监听数组 Vue2 对于数组提供了一些变异方法 重写数组方法源码分析 定义拦截器将拦截器挂载到数组上面收集依赖 扩展&#xff1a;理解Vue2如何解决数组和对象的响应式问题 对复杂对象的处理 复杂对…...

软考科目如何选择?

软考科目繁多&#xff0c;让许多学弟学妹感到困惑&#xff0c;不知道该选择哪个科目。以下是一些建议&#xff0c;可以根据个人实际需求选择备考的科目。 1、初级是可选的 软考初级非常简单&#xff0c;适合刚刚入门学习的朋友报考。对于一些有基础的朋友&#xff0c;建议直接…...

羊大师解读,血压波动

羊大师解读&#xff0c;血压波动 血压是身体健康的一个重要指标&#xff0c;但有时候我们会发现血压存在着波动的情况。血压波动的原因有很多&#xff0c;包括生活方式、遗传因素、药物影响等等。本文小编羊大师将为大家详细介绍血压波动的原因&#xff0c;以及预防和管理血压…...

关于充值!购买的流量卡第一次在哪充值?这个问题你想过吗?

手机套餐太贵、物联卡体验又不好&#xff0c;而官网申请的流量卡又都是定向流量&#xff0c;所以&#xff0c;运营商推出的只能线上申请的大流量卡一时之间便成了大家关注的焦点。 ​  在流量卡的使用过程中&#xff0c;申请是免费的&#xff0c;快递是免费的&#xff0c;但…...

HTML基础标签

但实际上无论声明为中文还是英文都可以写&#xff0c;中文/英文 主要是浏览器在进行调用翻译功能的时候&#xff0c;会按照声明的语言来进行翻译。 标签语义&#xff1a; 标签的属性一般都是在第一个标签中定义该标签效果所拥有的属性。 即标签的作用是什么 <>标签功能…...

人大金仓引领医疗行业新标准

近日&#xff0c;由中国信息产业商会团体标准委员会主办&#xff0c;人大金仓与国家电子计算机质量检验检测中心&#xff08;北京尊冠科技有限公司&#xff09;联合承办的《基于医疗应用的国产关系型数据库能力评价规范》团体标准研讨会顺利召开。 “ 各大知名医院专家云集 深入…...

【UML】NO.1 UML简介

目录 一、什么是UML 二、UML和软件工程 三、UML的诞生 四、UML的基本构成 从今天开始&#xff0c;开一个新的话题&#xff0c;把UML梳理一遍。 一、什么是UML UML&#xff08;Unified Modeling Language,UML&#xff09;是一个通用的可视化建模语言标准&#xff0c;用于对…...

【Idea】SpringBoot项目中,jar包引用冲突异常的排查 / SM2算法中使用bcprov-jdk15to18的报错冲突问题

问题描述以及解决方法&#xff1a; 项目中使用了bcprov-jdk15to18 pom依赖&#xff0c;但是发现代码中引入的版本不正确。 追溯代码发现版本引入的是bcprov-jdk15on&#xff0c;而不是bcprov-jdk15to18&#xff0c;但是我找了半天pom依赖也没有发现有引入bcprov-jdk15on依赖。…...

MISRA C++ 2023:C和C++测试解决方案实现静态分析

自动化软件测试解决方案的全球领导者Parasoft今天宣布&#xff0c;随着Parasoft C/Ctest 2023.2即将发布&#xff0c;全面支持MISRA C 2023。Parasoft针对C和C软件开发的完全集成测试解决方案计划于2023年12月发布&#xff0c;可以帮助团队实现自动化静态分析和编码标准合规性&…...

半导体:Gem/Secs基本协议库的开发(4)

继续接上篇 《半导体&#xff1a;Gem/Secs基本协议库的开发&#xff08;3&#xff09;》&#xff0c;本篇我们分享的比较简单&#xff0c;windows系统下tcp和串口通讯。这也是我们协议开发比较重要的一部分&#xff0c;不过我们在此把它封装程一个单独的通讯库&#xff0c;毕竟…...

解锁知识的新大门:自建知识付费小程序的技术指南

在数字化时代&#xff0c;知识付费小程序的崛起为创作者和学习者提供了全新的学习和分享方式。本文将以“知识付费小程序源码”为关键词&#xff0c;从技术角度出发&#xff0c;为你展示如何搭建一个独具特色的知识付费平台。 步骤1&#xff1a;选择适用的知识付费小程序源码…...

Java8实战 - 行为参数化传递代码

背景&#xff1a; 根据《java8实战》把第二章简单概括一下。 在软件工程中&#xff0c;一个最重要的问题是&#xff0c;用户的需求会一直变化&#xff0c;如何应对不断变化的需求&#xff0c;并且把工作量降到最低是需要考虑的&#xff0c;而行为参数化就是一个处理频繁变更需…...

jmeter,取“临时重定向的登录接口”响应头中的cookie

1、线程组--创建线程组&#xff1b; 2、线程组--添加--取样器--HTTP请求&#xff1b; 3、Http请求--添加--后置处理器--正则表达式提取器&#xff1b; 4、线程组--添加--监听器--查看结果树&#xff1b; 5、线程组--添加--取样器--调试取样器。 首先理解 自动重定向 与跟随…...

流程控制之条件判断

目录 流程控制之条件判断 2.1.if语句语法 2.1.1单分支结构 2.1.2双分支结构 2.1.3多分支结构 2.2.案例 例一: 例2: 例3: 例4: 例5: 例6: 例7: 例8: 例9: 2.3.case多条件判断 2.3.1.格式 2.3.2.执行过程 例10: 流程控制之条件判断 2.1.if语句语法 2.1.1单分…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...

comfyui 工作流中 图生视频 如何增加视频的长度到5秒

comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗&#xff1f; 在ComfyUI中实现图生视频并延长到5秒&#xff0c;需要结合多个扩展和技巧。以下是完整解决方案&#xff1a; 核心工作流配置&#xff08;24fps下5秒120帧&#xff09; #mermaid-svg-yP…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理

在城市的某个角落&#xff0c;一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延&#xff0c;滚滚浓烟弥漫开来&#xff0c;周围群众的生命财产安全受到严重威胁。就在这千钧一发之际&#xff0c;消防救援队伍迅速行动&#xff0c;而豪越科技消防一体化安全管控平台构建的消防“…...

AD学习(3)

1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分&#xff1a; &#xff08;1&#xff09;PCB焊盘&#xff1a;表层的铜 &#xff0c;top层的铜 &#xff08;2&#xff09;管脚序号&#xff1a;用来关联原理图中的管脚的序号&#xff0c;原理图的序号需要和PCB封装一一…...