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

AMS(ActivityManagerService)源码解析2,Android应用是如何被启动的

一个Android应用是如何被启动的

  • 前言
  • 总结
  • 1. 启动Application
    • 1.1 拉起一个新的进程
    • 1.2 启动Application
    • 1.3 AMS阶段
    • 1.4 创建Instrumentation和Application
  • 2. 启动Activity
    • 2.1 回到AMS,启动第一个Activity
  • 参考资料

前言

基于源码API 28,30以后的版本启动第一个Activity的逻辑不一样

我会只拿出我们需要关注的代码部分,因为源码太多全都看看不过来的。所以每次截代码都有省略
前言
源码只截取需要看的部分,其他部分会省略。

源码基于API 28也就是Android9.0,也就是源码还有ActivityStackSupervisor的这个版本
其他版本代码不太一样没有ActivityStackSupervisor,但是原理是相同的。

AOSP的源码在这个网站上看:http://aospxref.com/

总结

用流程总结app启动:

  1. 用户点击应用图标(或者其他方式打开app)
  2. 要打开app的进程(可能是桌面进程可能是别的Intent)通知zygote进程fork出一个新的进程用于承载app。
  3. ActivityThread通过main方法启动,通过跨进程通信,通知SystemServer进程
  4. SystemServer的AMS去找PMS拿对应的进程信息。
  5. AMS将进程信息PackageInfo返还给应用进程
  6. ActivityThread创建Instrumentation和通过反射的方式创建Application,
  7. Instrumentation调用application的生命周期。

用流程总结第一个Activity启动:

  1. AMS遍历mPackages里面的Activity标签之后,找到启动时所需要的那个Activity(根据Intent里面的那个启动标签)。
  2. 准备一个事务(clientTransaction),里面包括了Activity的启动(Callback)和拉到前台(lifecycleState)两件事。

后面的流程参考上一篇文章的第六节,我们只需要知道一旦往ActivityThread发了一个ClientTransaction之后,后面的流程就完全是固定的。

AMS(ActivityManagerService)源码解析,Activity是如何被打开的
https://blog.csdn.net/qq_41872247/article/details/125031721

1. 启动Application

1.1 拉起一个新的进程

首先我们需要明确一点的是,启动一个app,他的起点来自于桌面进程,桌面进程在用户点击app图标准备拉起app的时候,就会让Zygote进程去即使的fork一个新的app进程出来,然后寻找到这个新的app的ActivityThread类的Main方法进行执行。

这部分见https://blog.csdn.net/qq_41872247/article/details/125211491

1.2 启动Application

接下来我们就来到了ActivityThread的Main方法

public final class ActivityThread extends ClientTransactionHandlerimplements ActivityThreadInternal {private ApplicationThread mAppThread// 启动类public static void main(String[] args) {ActivityThread thread = new ActivityThread();thread.attach(false, startSeq);}private void attach(boolean system, long startSeq) {if(!system) {final IActivityManager mgr = ActivityManager.getService();try {mgr.attachApplication(mAppThread, startSeq);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}}}private class ApplicationThread extend IApplicationThread.Stub {}
}

到attach,我们就通过跨进程进行binder通信了,拿到了AMS对象。我们传的对象ApplicationThread就是ActivityThread的一个内部类,持有外部引用,这个类就是负责和AMS通信。

1.3 AMS阶段

public class ActivityManagerService extends IActivityManager.Stubimplements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {public final void attachApplication(IApplicationThread thread, long startSeq) {synchronized (this) {attachApplicationLocked(thread, callingPid, callingUid, startSeq);}}private boolean attachApplicationLocked(@NonNull IApplicationThread thread,int pid, int callingUid, long startSeq) {ProcessRecord app;// 这段代码从PMS中请求App的数据if (app == null && startSeq > 0) {final ProcessRecord pending = mPendingStarts.get(startSeq);if (pending != null && pending.startUid == callingUid && pending.startSeq == startSeq&& handleProcessStartedLocked(pending, pid, pending.usingWrapper,startSeq, true)) {app = pending;}}if (app.isolatedEntryPoint != null) {thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);} else if (app.instr != null) {// 走这里thread.bindApplication(processName, appInfo, providers,app.instr.mClass,profilerInfo, app.instr.mArguments,app.instr.mWatcher,app.instr.mUiAutomationConnection, testMode,mBinderTransactionTrackingEnabled, enableTrackAllocation,isRestrictedBackupMode || !normalMode, app.persistent,new Configuration(getGlobalConfiguration()), app.compat,getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked(),buildSerial, isAutofillCompatEnabled);} else {thread.bindApplication(processName, appInfo, providers, null, profilerInfo,null, null, null, testMode,mBinderTransactionTrackingEnabled, enableTrackAllocation,isRestrictedBackupMode || !normalMode, app.persistent,new Configuration(getGlobalConfiguration()), app.compat,getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked(),buildSerial, isAutofillCompatEnabled);}}
}

AMS这部分先去PMS里面拿到当前app的相关数据(之前写在AndroidManifest里面的解析后存在mPackages的内容),
然后再返回来给ApplicationThread(走到thread.bindApplication)。

1.4 创建Instrumentation和Application

public final class ActivityThread extends ClientTransactionHandlerimplements ActivityThreadInternal {private class ApplicationThread extend IApplicationThread.Stub {public final void bindApplication(很多入参) {AppBindData data = new AppBindData();// ....将App的数据都放进data里面sendMessage(H.BIND_APPLICATION, data);}}
}

这里第一次sendMsg了,就是handler的那套流程,最后走到的是外侧的一个bindApplication方法

public final class ActivityThread extends ClientTransactionHandlerimplements ActivityThreadInternal {private static class AndroidOs extends ForwardingOs {private void handleBindApplication(AppBindData data) {// 一般都是走上面if (ii != null) {initInstrumentation(ii, data, appContext);} else {mInstrumentation = new Instrumentation();mInstrumentation.basicInit(this);}//.....省略无关代码Application app;try {// 创建appllicationapp = data.info.makeApplicationInner(data.restrictedBackupMode, null);//......// Instrumentation自己的onCreate方法,等于自己的生命周期,忽视它mInstrumentation.onCreate(data.instrumentationArgs);//......mInstrumentation.callApplicationOnCreate(app);}}private void initInstrumentation(InstrumentationInfo ii, AppBindData data, ContextImpl appContext) {try {final ClassLoader cl = instrContext.getClassLoader();mInstrumentation = (Instrumentation)cl.loadClass(data.instrumentationName.getClassName()).newInstance();}//init只是把一大堆东西给他赋值到成员变量里面mInstrumentation.init(this, instrContext, appContext, component,data.instrumentationWatcher, data.instrumentationUiAutomationConnection);}}
}

他在这段代码中做了几件事:

  1. 创建Instrumentation对象
  2. 创建Application对象
  3. 调用Application的生命周期

Instrumentation的创建过程上面已经有了,接下来看makeApplicationInner是如何创建Application的:

public final class LoadedApk {private Application makeApplicationInner(boolean forceDefaultAppClass,Instrumentation instrumentation, boolean allowDuplicateInstances) {Application app = null;app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);return app;}
}public class Instrumentation {public Application newApplication(ClassLoader cl, String className, Context context)throws InstantiationException, IllegalAccessException, ClassNotFoundException {// getFactory我们具体就不看了,最终就是返回一个AppComponentFactory的对象Application app = getFactory(context.getPackageName()).instantiateApplication(cl, className);app.attach(context); //这个attach,就是我们自己定义的Application类的生命周期的那个attach,由Instrumentation直接调用return app;}
}public class AppComponentFactory {public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,@NonNull String className)throws InstantiationException, IllegalAccessException, ClassNotFoundException {// 走到最后还是反射创建的对象。return (Application) cl.loadClass(className).newInstance();}
}

虽然中间跨了很多个类,但是还是可以看得出来根本的那行代码还是反射创建Application对象。

最后看看Application的生命周期是如何被Instrumentation调用的

public class Instrumentation {public void callApplicationOnCreate(Application app) {app.onCreate();}
}

结果就是直接调用,没有任何转折。

2. 启动Activity

2.1 回到AMS,启动第一个Activity

  1. 代码回到AMS,刚刚AMS的代码还未执行完。
public class ActivityManagerService extends IActivityManager.Stubimplements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {private boolean attachApplicationLocked(@NonNull IApplicationThread thread,int pid, int callingUid, long startSeq) {//.. bind之后发生的事// See if the top visible activity is waiting to run in this process...// 查看在这个进程中顶部的Activity是否正在等待运行...   其实就是启动顶部Activity了if (normalMode) {try {if (mStackSupervisor.attachApplicationLocked(app)) {didSomething = true;}} catch (Exception e) {Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);badApp = true;}}}
}public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,RecentTasks.Callbacks {boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {final String processName = app.processName;boolean didSomething = false;for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {final ActivityStack stack = display.getChildAt(stackNdx);if (!isFocusedStack(stack)) {continue;}stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);final ActivityRecord top = stack.topRunningActivityLocked();final int size = mTmpActivityList.size();for (int i = 0; i < size; i++) {final ActivityRecord activity = mTmpActivityList.get(i);if (activity.app == null && app.uid == activity.info.applicationInfo.uid&& processName.equals(activity.processName)) {try {// 通过好几层的for循环遍历app里面所有的Activity,去寻找并启动app的启动页if (realStartActivityLocked(activity, app,top == activity /* andResume */, true /* checkConfig */)) {didSomething = true;}} catch (RemoteException e) {throw e;}}}}}if (!didSomething) {ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);}return didSomething;}final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,boolean andResume, boolean checkConfig) throws RemoteException {try {// 准备启动Activity的事务final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,r.appToken);// 这里准备了一个LaunchActivityItem作为Callback,记住他,后面会用到clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),System.identityHashCode(r), r.info,mergedConfiguration.getGlobalConfiguration(),mergedConfiguration.getOverrideConfiguration(), r.compat,r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,r.persistentState, results, newIntents, mService.isNextTransitionForward(),profilerInfo));final ActivityLifecycleItem lifecycleItem;if (andResume) {// 这里我们是启动Activity,所以走resumelifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());} else {lifecycleItem = PauseActivityItem.obtain();}// 这里准备了一个ResumeActivityItem作为LifecycleState,记住他,后面会用到clientTransaction.setLifecycleStateRequest(lifecycleItem);// 发送这个事务mService.getLifecycleManager().scheduleTransaction(clientTransaction);}}
}

AMS遍历了一下启动进程的所有Activity,找到启动时要用的那个,走到了realStartActivityLocked准备启动。

后面的流程参考这篇文章的第六节,是完全一样的
AMS(ActivityManagerService)源码解析,Activity是如何被打开的
https://blog.csdn.net/qq_41872247/article/details/125031721

参考资料

码牛学院VIP课程 VIP12-2021.12.03-這染机制-01 Activity. View. WMS的协调kerwin

AOSP的源码网站:http://aospxref.com/

相关文章:

AMS(ActivityManagerService)源码解析2,Android应用是如何被启动的

一个Android应用是如何被启动的 前言总结1. 启动Application1.1 拉起一个新的进程1.2 启动Application1.3 AMS阶段1.4 创建Instrumentation和Application 2. 启动Activity2.1 回到AMS&#xff0c;启动第一个Activity 参考资料 前言 基于源码API 28&#xff0c;30以后的版本启动…...

数据库事务隔离级别

前几天项目上合作公司的系统出现了一次死锁&#xff0c;突然想到由于近几年开发设计的系统并发用户比较少&#xff0c;很久没有碰到过死锁了&#xff0c;因此对死锁的概念也比较生疏了&#xff0c;需要温习一下。 事务 先从最基本的概念开始&#xff0c;事务、及其ACID特性。…...

Pytest 记录日志输出到控制台和写入文件

目录 自定义日志记录器和内置的日志记录器 项目代码 项目目录树 自定义日志记录器 函数源代码 pytest中定义和覆盖日志记录信息 使用cli定义Logging 使用pytest.ini定义Logging 修改单个测试级别的日志 日志输出的重要性不言而喻&#xff0c;不仅可以观测执行过程&…...

LINUX网络FTP服务

一、FTP服务 FTP服务&#xff1a;file transfer protocol :文件传输协议。在网络上进行双向传输&#xff0c;也是一个应用程序。不同的操作系统有不同的FTP软件&#xff0c;但使用的协议是一样的。 FTP协议基于TCP协议&#xff0c;有两个端口&#xff0c;即20和21。 20端口&…...

10 C++11

10 C11 1、类型推导1.1 auto关键字1.2 auto类型推断本质 2、类型计算2.1 类型计算分类2.2 类型计算的四种规则2.3 返回值类型计算 3、列表初始化4、Lambda表达式4.1 前置知识4.2 Lambda表达式4.3 捕获表 5、右值引用5.1 概念5.2 左值引用和右值引用 6、移动语义 1、类型推导 1…...

java的封装

为什么要封装&#xff1f;在java的面向对象的思想中&#xff0c;封装是指将类的实现细节包装&#xff0c;隐藏起来的方法。封装可以防止本类的代码和数据被外部定义的代码随机访问。 如何进行封装&#xff1f; 在定义一个类时&#xff0c;将类中的属性私有化&#xff0c;即使…...

为什么选择海外服务器?

如何选择跨境电商服务器&#xff1a;详细指南 选择合适的服务器是跨境电商企业成功的基础。服务器的性能和稳定性直接影响着网站的访问速度、用户体验和安全性&#xff0c;进而影响着企业的销量和利润。那么&#xff0c;跨境电商企业该如何选择服务器呢&#xff1f; 1. 确定目…...

k8s+springcloud+nacos部署配置

1 k8s 部署nacos-2.1.2配置k8s-nacos-statefulSet.yaml文件 apiVersion: v1 kind: Service metadata:name: nacos-headlessnamespace: rz-dtlabels:app: nacosannotations:service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" spec:# 3个端口打开&…...

梯度提升决策树(GBDT)

GBDT&#xff08;Gradient Boosting Decision Tree&#xff09;&#xff0c;全名叫梯度提升决策树&#xff0c;是一种迭代的决策树算法&#xff0c;又叫 MART&#xff08;Multiple Additive Regression Tree&#xff09;&#xff0c;它通过构造一组弱的学习器&#xff08;树&am…...

数据结构之B树的原理与业务场景

B树是一种自平衡的树形数据结构&#xff0c;它能够保持数据有序&#xff0c;并且可以高效地进行查找、顺序访问、插入和删除操作。B树的设计是为了优化磁盘I/O操作&#xff0c;因为它可以减少磁盘访问次数&#xff0c;这在数据库和文件系统中非常有用。 1. B树的原理 节点的出…...

【Android面试八股文】你能说一说线程池管理线程的原理吗?

面试官(Interviewer): 欢迎参加面试,今天我们会讨论一些关于 Java 线程池管理的问题。你能给我解释一下 ThreadPoolExecutor 是如何管理线程的吗? 候选人(Candidate): 当然可以,ThreadPoolExecutor 是 Java 中用于创建和管理线程池的核心类。它通过一组核心参数来控制线…...

springer 在线投稿编译踩坑

springer投稿&#xff0c;在线编译踩坑总结 注意&#xff1a; 有的期刊需要双栏&#xff0c;而预定义的模板中可能为单栏&#xff0c;需要增加iicol选项。 例如&#xff1a; \documentclass[sn-mathphys-num]{sn-jnl}% —>\documentclass[sn-mathphys-num, iicol]{sn-jnl}…...

固态硬盘的指标

固态硬盘的指标主要包括以下几个方面&#xff1a; 接口类型&#xff1a;这是固态硬盘与外部设备连接的方式&#xff0c;常见的接口类型有SATA、PCIe和NVMe等。不同的接口类型决定了固态硬盘的传输速度和性能。例如&#xff0c;PCIe接口的固态硬盘通常比SATA接口的固态硬盘具有…...

mysql 分组后每个取最新的一条记录

在MySQL中&#xff0c;若要从一个分组中获取每组的最新一条记录&#xff08;通常基于时间戳或其他递增的列&#xff09;&#xff0c;可以使用子查询或者窗口函数&#xff08;如果MySQL版本支持&#xff09;。 以下是两种不同的实现方法&#xff1a; 方法1: 使用子查询和LIMIT…...

Java语法和基本结构介绍

Java语法和基本结构是Java编程的基础&#xff0c;它决定了Java代码的书写方式和程序的结构。以下是Java语法和基本结构的一些关键点&#xff1a; 1.标识符和关键字&#xff1a;Java中的标识符是用来标识变量、函数、类或其他用户自定义元素的名称。关键字是预留的标识符&#x…...

TDengine 3.3.0.0 引入图形化管理工具、复合主键等 13 项关键更新

在涛思数据研发团队的努力下&#xff0c;TDengine 3.3.0.0 版本终于和大家见面了。这一版本中&#xff0c;我们引入了多项革新功能和性能优化&#xff0c;力求在为用户提供极致体验的同时&#xff0c;不断推动技术的前沿。 此次更新不仅针对开源社区版本&#xff0c;进行了一系…...

C++基础之红黑树

二叉搜索树 二叉搜索树&#xff08;Binary Search Tree&#xff0c;BST&#xff09;是一种二叉树&#xff0c;具有以下性质&#xff1a; 左子树节点值小于根节点值&#xff1a;对于树中的每个节点 x&#xff0c;其左子树中所有节点的值都小于 x 的值。右子树节点值大于根节点值…...

ClickHouse数据库对比、适用场景与入门指南

本文全面对比了ClickHouse与其他数据库&#xff08;如StarRocks、HBase、MySQL、Hive、Elasticsearch等&#xff09;的性能、功能、适用场景&#xff0c;并提供了ClickHouse的教学入门指南&#xff0c;旨在帮助读者选择合适的数据库产品并快速掌握ClickHouse的使用。 文章目录 …...

举例说明 如何通过SparkUI和日志定位任务莫名失败?

有一个Task OOM&#xff1a; 通过概览信息&#xff0c;发现Stage 10的Task 36失败了4次导致Job失败。概览信息中显示最后一次失败的退出代码&#xff08;exit code&#xff09;是143&#xff0c;意味着发生了内存溢出&#xff08;OOM&#xff0c;即Out of Memory&#xff09;。…...

Vue前端通过Axios的post方式传输数据,后端为什么一直接收的值是null?

沃靠!这个细节太细了,搞了我两个多小时才找到这个bug。 一、 首先官方文档给我的post请求的例子是这样的: axios.post(/user, {firstName: Fred,lastName: Flintstone}).then(function (response) {console.log(response);}).catch(function (error) {console.log(error);})…...

外链建设如何进行?

理解dofollow和nofollow链接&#xff0c;所谓dofollow链接&#xff0c;就是可以传递权重到你的网站的链接&#xff0c;这种链接对你的网站排名非常有帮助&#xff0c;这种链接可以推动你的网站在搜索结果中的位置向上爬&#xff0c;但一个网站全是这种有用的链接&#xff0c;反…...

深入理解Java正则表达式及其应用

正则表达式是一种强大的文本匹配和处理工具&#xff0c;可以在字符串中查找、替换、提取符合特定模式的内容。Java作为一种广泛应用的编程语言&#xff0c;提供了丰富的正则表达式支持。本文将深入探讨Java正则表达式的基本概念、语法以及常见应用场景&#xff0c;帮助读者全面…...

Gstreamer学习3----灌数据给管线之appsrc

参考资料 Basic tutorial 8: Short-cutting the pipeline gstreamer向appsrc发送帧画面的代码_gst appsrc可变帧率-CSDN博客 在官网教程Basic tutorial 8: Short-cutting the pipeline 里面&#xff0c;讲了一个例子&#xff0c;push音频数据给管线&#xff0c;视频的例子更…...

【深度学习量化交易1】一个金融小白尝试量化交易的设想、畅享和遐想

关注我的朋友们可能知道&#xff0c;我经常在信号处理的领域出没&#xff0c;时不时会发一些信号处理、深度学习科普向的文章。 不过算法研究久了&#xff0c;总想做一些更有趣的事情。 比如用深度学习算法赚大钱。。毕竟有什么事情能比暴富更有意思呢。 一、神经网络与彩票…...

【0基础学爬虫】爬虫基础之自动化工具 DrissionPage 的使用

概述 前三期文章中已经介绍到了 Selenium 与 Playwright 、Pyppeteer 的使用方法&#xff0c;它们的功能都非常强大。而本期要讲的 DrissionPage 更为独特&#xff0c;强大&#xff0c;而且使用更为方便&#xff0c;目前检测少&#xff0c;强烈推荐&#xff01;&#xff01;&a…...

c++_0基础_讲解7 练习

这一讲我为大家准备了几道题目&#xff0c;大家试着独自做一下&#xff08;可能来自不同网站&#xff09; 整数大小比较 - 洛谷 题目描述 输入两个整数&#xff0c;比较它们的大小。若 x>yx>y &#xff0c;输出 > &#xff1b;若 xyxy &#xff0c;输出 &#xff…...

docker一些常用命令以及镜像构建完后部署到K8s上

docker一些常用命令以及镜像构建完后部署到K8s上 1.创建文件夹2.删除文件3.复制现有文件内容到新建文件4.打开某个文件5.查看文件列表6.解压文件&#xff08;tar格式&#xff09;7.解压镜像8.查看镜像9.删除镜像10.查看容器11.删除容器12.停止运行容器13.构建镜像14.启动容器15…...

在typora中利用正则表达式,批量处理图片

一&#xff0c;png格式 在 Typora 中批量将 HTML 图片标签转换为简化的 Markdown 图片链接&#xff0c;且忽略 alt 和 style 属性&#xff0c;可以按照以下步骤操作&#xff1a; 打开 Typora 并加载你的文档。按下 Ctrl H&#xff08;在 Windows/Linux 上&#xff09;或 Cmd…...

构建LangChain应用程序的示例代码:33、如何在LangChain框架中使用HumanInputChatModel来模拟人工输入的聊天模型教程

除了HumanInputLLM&#xff0c;LangChain还提供了一个伪聊天模型类&#xff0c;可以用于测试、调试或教育目的。这允许您模拟对聊天模型的调用&#xff0c;并模拟如果人类接收到这些消息会如何响应。 在这篇笔记中&#xff0c;我们将介绍如何使用这个模型。 我们首先在代理中…...

虚拟机使用桥接模式网络配置

1、获取本机的网络详细信息 windowr 输入cmd 使用ipconfig -all 一样即可 在自己的虚拟机中设置网络 虚拟机中的ip ---------192.168.36.*&#xff0c;不要跟自己的本机ip冲突 网关-----------192.168.36.254 一样即可 dns -----------一样即可&#xff0c;我多写了几个&am…...

网站建设的技巧有哪些方面/武汉seo托管公司

引言&#xff1a;NFT Insider由NFT收藏组织WHALE Members、BeepCrypto联合出品&#xff0c;浓缩每周NFT新闻&#xff0c;为大家带来关于NFT最全面、最新鲜、最有价值的讯息。每期周报将从NFT市场数据&#xff0c;艺术新闻类&#xff0c;游戏新闻类&#xff0c;虚拟世界类&#…...

做设计的地图网站/网站怎样优化文章关键词

ZMQ (以下 ZeroMQ 简称 ZMQ)是一个简单好用的传输层&#xff0c;像框架一样的一个 socket library&#xff0c;他使得 Socket 编程更加简单、简洁和性能更高。是一个消息处理队列库&#xff0c;可在多个线程、内核和主机盒之间弹性伸缩。ZMQ 的明确目标是“成为标准网络协议栈的…...

怎样建设微网站/首页百度

This group of metrics gives you the availability and status of the managed database. Metrics include:Database Status、Database Process Check、aximum # of sessions since startup and Availability. 在Oracle10G中引入了metric&#xff0c;用来监控数据库表空间&a…...

唐山网站制作app/2023年最新新闻简短摘抄

文章目录前言一、四大基础理论1.拜占庭将军问题2.CAP 理论3.ACID 理论4.BASE 理论二、八大分布式协议和算法1.Paxos 算法2.Raft 算法3.Gossip 协议算法4.Quorum NWR 算法5.一致性 Hash 算法6.FBFT 算法7.POW 算法8.ZAB 协议总结前言 本文将系统介绍有关分布式有关的理论基础和相…...

阿里云空间可以做网站吗/外贸网站免费推广

一、诈骗罪的起刑点以及量刑是怎么规定的 1、诈骗罪起刑点为诈骗的公私财物价值达到三千元。 2、诈骗罪的量刑标准如下所述&#xff1a; &#xff08;1&#xff09;数额较大的&#xff0c;处三年以下有期徒刑、拘役或者管制&#xff0c;并处或者单处罚金; &#xff08;2&am…...

咸阳免费做网站/国际形势最新消息

字符串String类 1.字符串全部在方法区的常量池里面 2.涉及到字符串内容比较用equals()方法 3.当“”运算符两侧的操作数中只要有一个是字符串&#xff08;String&#xff09;类型&#xff0c;系统会自动将另一个操作数转换为字符串&#xff08;String&#xff09;类型然后进行连…...