JAVA-JVM 内存模型类加载器GC算法GC调优

news2024/9/21 3:42:06

在这里插入图片描述

JAVA-JVM 内存模型&类加载器&GC算法&GC调优

  • 什么是JVM
  • JVM 内存模型
  • JVM的GC算法
  • JVM类加载器

什么是JVM

?
[[jvm]]是Java Virtual Machine(Java虚拟机)的缩写,JVM是一个虚构出来的计算机,有着自己完善的硬件架构,如处理器、堆栈等。

为什么需要JVM?

?
我们都知道 Java 源文件,通过编译器,能够生产相应的.Class 文件,也就是字节码文件, 而字节码文件又通过 Java 虚拟机中的解释器,编译成特定机器上的机器码 。 也就是如下: ① Java 源文件—->编译器—->字节码文件
② 字节码文件—->JVM—->机器码
每一种平台的解释器是不同的,但是实现的虚拟机是相同的,这也就是 Java 为什么能够 跨平台的原因了 ,当一个程序从开始运行,这时虚拟机就开始实例化了,多个程序启动就会 存在多个虚拟机实例。程序退出或者关闭,则虚拟机实例消亡,多个虚拟机实例之间数据不能共享

JVM内存模型

在这里插入图片描述

内存区域作用特点
程序计数器一块较小的内存空间,当前线程所执行字节码的行号指示器线程私有,不会内存溢出
Java 虚拟机栈存储栈帧,用于方法执行线程私有,可能出现 StackOverflowError 和 OutOfMemoryError
本地方法栈存储本地方法的栈帧线程私有,情况与 Java 虚拟机栈类似
Java 堆存储对象实例和数组等被所有线程共享,可能出现 OutOfMemoryError
方法区存储已被虚拟机加载的类信息、常量、静态变量等被所有线程共享,JDK 8 及之后用元空间实现,可能出现 OutOfMemoryError
运行时常量池存放编译期生成的各种字面量和符号引用方法区的一部分,具有动态性

Jvm Heap 堆分区

Heap内存逻辑分区

?
堆大小 = 新生代 + 老年代。其中,堆的大小可以通过参数 –Xms-Xmx 指定。
Java 堆从 GC 的角度还可以细分为: 新生代(Eden 区、From Survivor 区和 To Survivor 区)和老年 代。
![[041fed343517d517381a83a26a211202.png]]

1、新生代
Eden + Survivor
- eden:对象最初创建的区域
- survivor:eden幸存下来的对象所在的区域。
2、老年代
主要存放程序中年龄较大和需要占用大量内存空间的对象
老年代的对象比较稳定,所以 ·MajorGC 不会频繁执行。在进行 MajorGC 前一般都先进行 了一次 MinorGC,使得有新生代的对象晋身入老年代,导致空间不够用时才触发。当无法找到足 够大的连续空间分配给新创建的较大对象时也会提前触发一次 MajorGC 进行垃圾回收腾出空间。
在 HotSpot 虚拟机中,新生代默认情况下 Eden 和 Survivor 的比例是 8:1:1。
即 Eden 区占新生代空间的 8/10,Survivor0(S0)和 Survivor1(S1)各占新生代空间的 1/10。

这样的比例设置主要是为了在进行 Minor GC 时,能够有足够的空间存储存活的对象,同时也尽量减少复制操作的开销。如果 Survivor 区设置得太小,可能会导致一些存活时间较长的对象过早地晋升到老年代,增加老年代的压力;如果设置得太大,又会浪费新生代的空间。

MajorGC 采用标记清除算法:首先扫描一次所有老年代,标记出存活的对象,然后回收没 有标记的对象。MajorGC 的耗时比较长,因为要扫描再回收。MajorGC 会产生内存碎片,为了减 少内存损耗,我们一般需要进行合并或者标记出来方便下次直接分配。当老年代也满了装不下的 时候,就会抛出 OOM(Out of Memory)异常。

新生代和老年代的作用?
?

title: 答
**新生代**
作用:
  主要用来存放新创建的对象。大多数对象在创建后不久就会变得不可达,因此新生代适合使用`复制算法`进行垃圾回收。
  新生代的目的是`快速回收那些生命周期短的对象,减少内存碎片的产生`。

组成:
一般分为 
- Eden 区
- Survivor0(S0)区
- Survivor1(S1)区。

新创建的对象首先在 Eden 区分配内存。当 Eden 区满时,会触发一次 Minor GC(小型垃圾回收),将 Eden 区和其中一个 Survivor 区(比如 S0)中仍然存活的对象复制到另一个 Survivor 区(S1)中。经过多次 Minor GC 后仍然存活的对象会被晋升到老年代。

**老年代**
作用
存放生命周期较长的对象。这些对象经过多次垃圾回收后仍然存活,或者是一些大对象直接在老年代分配内存。
==老年代的垃圾回收频率相对较低,但是每次回收所花费的时间较长==。
**特点**:
一般使用`标记 - 整理算法`或`标记 - 清除算法`进行垃圾回收。因为老年代中的对象通常比较稳定,不适合使用复制算法,否则会浪费大量的内存空间进行复制操作。
Minor GC(小型垃圾回收)

?
Minor GC(小型垃圾回收)是 Java 虚拟机中针对新生代的垃圾回收操作。
一、触发时机
当新生代内存空间不足时,就会触发 Minor GC。例如,新创建的对象不断在新生代的 Eden 区分配内存,当 Eden 区满了之后,就会触发一次 Minor GC。
二、执行过程

  1. 首先,将 Eden 区和其中一个 Survivor 区(比如 S0)中仍然存活的对象复制到另一个 Survivor 区(S1)中。
  2. 然后,清空 Eden 区和刚才作为源 Survivor 区(S0)的内存空间。
  3. 经过多次 Minor GC 后,仍然存活的对象会被晋升到老年代。
    三、特点
  4. 回收速度相对较快,因为新生代中的对象通常生命周期较短,数量相对较少,所以垃圾回收的时间较短。
  5. 较为频繁,由于新创建的对象大多在新生代,而且很多对象很快就会变成垃圾,所以 Minor GC 可能会比较频繁地发生
Major GC(大型垃圾回收)

?
Major GC(大型垃圾回收)是 Java 虚拟机中针对老年代的垃圾回收操作。
一、触发时机

  1. 老年代空间不足时触发。当老年代中的对象占用的内存空间达到一定比例或者老年代剩余空间无法容纳新的对象时,就会触发 Major GC。
  2. 有时候在 Minor GC 之前,JVM 可能会检查老年代的可用空间,如果老年代空间不足以容纳从新生代晋升过来的对象,也会触发 Major GC。
    二、执行过程
  3. 标记阶段:首先标记出老年代中仍然存活的对象。这个过程可能会遍历整个老年代以及从老年代到新生代的引用,以确定哪些对象是可达的。
  4. 清理阶段:对于标记为不可达的对象进行清理,释放它们占用的内存空间。根据不同的垃圾回收算法,清理阶段的具体操作会有所不同。
    • 如果采用标记 - 清除算法,会直接清理被标记为不可达的对象,但可能会产生内存碎片。
    • 如果采用标记 - 整理算法,在清理的同时会对存活的对象进行整理,将它们移动到一端,使内存空间更加连续。
      三、特点
  5. 回收速度相对较慢。因为老年代中的对象通常数量较多,而且可能存在大量的长期存活对象,所以垃圾回收的时间会比较长。
  6. 频率较低。由于老年代中的对象相对稳定,不像新生代中的对象那样频繁地变成垃圾,所以 Major GC 的发生频率要比 Minor GC 低得多。

Full GC(全量垃圾回收)

?
Full GC(全量垃圾回收)是对整个 Java 堆(包括新生代和老年代)进行的垃圾回收操作。
触发时机

  1. 老年代空间不足:当老年代中的对象占用的内存空间达到一定比例或者老年代剩余空间无法容纳新的对象时,会触发 Full GC。
  2. 永久代 / 元空间(在 JDK 8 及之后)空间不足:如果永久代 / 元空间中存储的类信息、常量、静态变量等占用的内存空间达到一定限制,也会触发 Full GC。
  3. System.gc () 被调用:在代码中显式地调用 System.gc () 方法会建议 JVM 进行垃圾回收,但 JVM 不一定会立即执行 Full GC,具体是否执行以及执行的时机取决于 JVM 的实现和当前的运行状态。
  4. CMS 垃圾回收器在进行并发标记和并发清理过程中出现 “Concurrent Mode Failure”:当 CMS 垃圾回收器在并发标记阶段,由于老年代中的对象增长速度过快,导致在并发清理阶段开始之前,老年代已经没有足够的空间来容纳新分配的对象,这时会触发 Full GC,并切换到 Serial Old 垃圾回收器进行老年代的回收。
    影响
  5. 停顿时间较长:由于 Full GC 需要扫描整个堆内存,所以它的执行时间通常比 Minor GC 要长得多。在 Full GC 执行期间,应用程序会暂停所有的线程,这可能会导致应用程序出现明显的停顿,影响用户体验。
  6. 资源消耗较大:Full GC 需要消耗大量的 CPU 和内存资源,这可能会影响应用程序的其他部分的性能。
    为了减少 Full GC 的发生频率,可以采取合理调整堆内存大小、优化对象创建和生命周期管理、选择合适的垃圾回收器、监控和分析垃圾回收情况等措施。

如何确定垃圾?

?
垃圾搜索算法

  • 引用计数法
  • 可达性分析法 (根搜索 Root Seaching)
  • 三色标记
    NOTE:
    在Java语言中,可作为GC Roots的对象包括下面几种:
  • 虚拟机栈(栈桢中的本地变量表)中的引用的对象
  • 方法区中的类静态属性引用的对象
  • 方法区中的常量引用的对象
  • 本地方法栈中JNI(Native方法)的引用的对象

垃圾收集算法

??
一、标记清除算法
1. 算法过程

  • 分为标注和清除两个阶段。首先从根集合进行两次扫描,在标记阶段标记出所有需要回收的对象,然后在清除阶段回收被标记的对象所占用的空间。
    2. 适用场景
  • 存活对象比较多的情况下使用,多用于老年代
    3. 优缺点
  • 优点:算法相对简单,实现容易。
  • 缺点:需要扫描两次,效率比较低;容易产生内存碎片化问题,可能导致后续大对象无法找到可利用空间。
    二、复制算法
    1. 算法过程
  • 按内存容量将内存划分为等大小的两块。每次只使用其中一块,当这一块内存满后,从根集合进行一次扫描,对存活的对象进行标记,然后将尚存活的对象复制到另一块上去,最后把已使用的内存清掉。
    2. 适用场景
  • 存活对象比较少的情况下使用,多用于年轻代。
    3. 优缺点
  • 优点:实现简单,内存效率高,不易产生碎片。
  • 缺点:可用内存被压缩到了原本的一半,且存活对象增多的话,效率会大大降低;需要调整对象的引用。
    三、标记整理算法
    1. 算法过程
  • 标记阶段和标记清除算法相同,标记后不是清理对象,而是将存活对象移向内存的一端,然后清除端边界外的对象。
    2. 适用场景
  • 可用于老年代等场景。
    3. 优缺点
  • 优点:不会产生内存碎片,不会造成空间浪费。
  • 缺点:需要扫描两次,需要调整对象的引用。
    四、分代收集算法
    1. 算法思想
  • 根据对象存活周期的不同将内存划分为几块,一般分为新生代和老年代。
  • 在新生代中,由于每次垃圾收集时都有大批对象死去,只有少量存活,选用复制算法。
  • 在老年代中,因为对象存活率高、没有额外空间对它进行分配担保,就必须使用 “标记 — 清理” 或者 “标记 — 整理” 算法来进行回收。

GC事件分类

?
垃圾回收(GC)事件可以分为以下几类:

  1. Young GC (又称Minor GC)
    新生代内存的垃圾收集事件称为Young GC(又称Minor GC),当JVM无法为新对象分配在新生代内存空间时总会触发 Young GC,比如 Eden 区占满时。新对象分配频率越高, Young GC 的频率就越高
    Young GC 每次都会引起全线停顿(Stop-The-World),暂停所有的应用线程,停顿时间相对老年代GC的造成的停顿,几乎可以忽略不计
  2. Old GC (又称Major GC)
    只清理老年代空间的GC事件,只有CMS的并发收集是这个模式
  3. Full GC
    清理整个堆的GC事件,包括新生代、老年代、元空间等
  4. Mixed GC
    清理整个新生代以及部分老年代的GC,只有G1有这个模式
避免 Full GC 或减少其发生频率的常用方法:

?

一、合理设置 JVM 参数

  • 设置合适的堆大小:
    -Xms(初始堆大小) -Xmx(最大堆大小)应该根据应用程序的实际需求进行设置。如果堆设置得过小,会导致频繁的垃圾回收;如果设置得过大,虽然可以减少垃圾回收的频率,但会增加垃圾回收的时间。一般来说,可以通过监控工具观察应用程序的内存使用情况,逐步调整堆大小以找到一个合适的平衡点。
  • 调整新生代和老年代的比例:通过 -XX:NewRatio 可以设置新生代和老年代的比例。如果新生代设置得太小,对象会很快晋升到老年代,增加老年代的压力;如果设置得太大,可能会浪费新生代的空间。可以根据应用程序的对象生命周期特点来调整这个比例。
  • 选择合适的垃圾回收器:
    不同的垃圾回收器有不同的特点和适用场景。例如,对于响应时间要求较高的应用程序,可以选择 CMS(Concurrent Mark Sweep)或 G1(Garbage-First)垃圾回收器。
    G1 垃圾回收器可以更好地控制垃圾回收的停顿时间,并且可以同时对新生代和老年代进行垃圾回收。但它需要一定的调优才能发挥最佳性能。

二、优化代码

  • 避免在循环中创建大量不必要的对象:尽量减少在循环中创建对象的次数,可以考虑对象复用或者使用数据结构来减少对象的创建。
  • 及时释放资源:对于不再使用的对象,及时将其引用置为 null,以便垃圾回收器能够回收它们所占用的内存空间。特别是对于一些占用较大内存的资源,如数据库连接、文件流等,要及时关闭和释放。
  • 选择合适的数据结构:使用合适的数据结构可以减少内存占用和对象的创建。例如,使用基本数据类型代替包装类,使用 StringBuilder 或 StringBuffer 代替频繁拼接字符串等。

三、监控和分析

  • 使用监控工具:如 JConsole、VisualVM 等工具可以实时监控 JVM 的内存使用情况、垃圾回收情况等。通过监控可以及时发现内存问题,并采取相应的措施进行优化。
  • 分析垃圾回收日志:垃圾回收日志中包含了丰富的信息,如垃圾回收的类型、时间、回收的对象数量等。通过分析垃圾回收日志可以了解垃圾回收的情况,找出可能导致 Full GC 的原因,并进行针对性的优化。
    例如,在一个 Web 应用程序中,可以通过以下方式来避免 Full GC:
    根据应用程序的实际需求,合理设置堆大小和新生代、老年代的比例。例如,如果应用程序处理的请求较多,可能需要较大的堆空间来避免频繁的垃圾回收。
    在代码中,避免在循环中频繁创建大对象,可以考虑使用对象池来复用对象。对于数据库连接等资源,要及时关闭和释放。
    使用监控工具实时监控应用程序的内存使用情况和垃圾回收情况。如果发现老年代的使用增长较快,可以分析代码中是否存在内存泄漏或者对象晋升过快的问题,并进行相应的优化。

垃圾回收器

?

G1

Garbage first 垃圾收集器是目前垃圾收集器理论发展的最前沿成果,相比与 CMS 收集器,G1 收 集器两个最突出的改进是:

  1. 基于标记-整理算法,不产生内存碎片。
  2. 可以非常精确控制停顿时间,在不牺牲吞吐量前提下,实现低停顿垃圾回收

G1 收集器避免全区域垃圾收集,它把堆内存划分为大小固定的几个独立区域,并且跟踪这些区域 的垃圾收集进度,同时在后台维护一个优先级列表,每次根据所允许的收集时间,优先回收垃圾 最多的区域区域划分优先级区域回收机制,确保 G1 收集器可以在有限时间获得最高的垃圾收 集效率。

GC调优

GC调优目标

?
大多数情况下对 Java 程序进行GC调优, 主要关注两个目标:响应速度吞吐量

  • 响应速度(Responsiveness) 响应速度指程序或系统对一个请求的响应有多迅速。比如,用户订单查询响应时间,对响应速度要求很高的系统,较大的停顿时间是不可接受的。
    • 调优的重点是在短的时间内快速响应
  • 吞吐量(Throughput) 吞吐量关注在一个特定时间段内应用系统的最大工作量,例如每小时批处理系统能完成的任务数量,在吞吐量方面优化的系统,较长的GC停顿时间也是可以接受的,因为高吞吐量应用更关心的是如何尽可能快地完成整个任务,不考虑快速响应用户请求

GC日志分析
?
GC日志是一个很重要的工具,它准确记录了每一次的GC的执行时间和执行结果,通过分析GC日志可以调优堆设置和GC设置,或者改进应用程序的对象分配模式
开启的JVM启动参数

-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps  -XX:+PrintGCTimeStamps
 

免费的GC日志图形分析工具推荐下面2个:
?

  • GCViewer,下载jar包直接运行
  • gceasy,web工具,上传GC日志在线使用

垃圾回收器的优化策略

?

堆内存的优化

对GC优化最有效最基础的办法就是调整堆的大小。堆是否需要扩大、要扩多大是一个取舍的问题。如果堆太小,JVM会频繁的进行GC
我们可以给JVM设置一个非常大的堆,但是如果设置一个非常大的堆会面临三个问题:

  1. 需要占用更多的系统资源。
  2. 虽然GC频率降低了但是每次GC要扫描的内容变多了,每次GC的停顿会增加了。
  3. 可能遇见虚拟内存的问题。如果系统进行了内存交换,将内存不活跃的数据复制到磁盘中,这个时候JVM尝试进行GC的时候会生成很大的性能开销,这个时候GC的开销会有数量级的增长。
    特别注意:调整堆大小永远不要超过机器的物理内存,如果存在多个JVM,则需要考虑所有JVM设置的总和。通常要给操作系统预留1G的空间
    [[JVM性能调优#垃圾回收器的优化策略]]

java3种类加载器

?
JVM 提 供了 3 种类加载器

  1. 启动类加载器(Bootstrap ClassLoader) ·
    负责加载 JAVA_HOME/lib 目录中的,或通过-Xbootclasspath 参数指定路径中的,且被 虚拟机认可(按文件名识别,如 rt.jar)的类。
  2. 扩展类加载器(Extension ClassLoader)
    负责加载 JAVA_HOME/lib/ext 目录中的,或通过 java.ext.dirs 系统变量指定路径中的类 库。
  3. 应用程序类加载器(Application ClassLoader)
    负责加载用户路径(classpath)上的类库。 JVM 通过双亲委派模型进行类的加载,当然我们也可以通过继承 java.lang.ClassLoader 实现自定义的类加载器

类加载器的双亲委派机制
?

双亲委派

![[9aea74185d5490bcf19f9d945690b3eb.png]]

当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载其中, 只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的 Class),子类加载器才会尝试自己去加载。
NOTE:
采用双亲委派的一个好处是比如加载位于 rt.jar 包中的类 java.lang.Object,不管是哪个加载 器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载 器最终得到的都是同样一个 Object 对象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2103030.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qwen-7B-Chat大模型安装训练推理-helloworld

初始大模型之helloworld编写 开发环境:modelscope GPU版本上测试的,GPU免费36小时 ps:可以不用conda直接用环境自带的python环境使用 魔搭社区 安装conda wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh 1.2 bash Mini…

港科夜闻 | 香港科大举办开学嘉年华,叶玉如校长勉励新生发掘潜能传承凡事皆可为精神...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科大举办开学嘉年华,叶玉如校长勉励新生发掘潜能传承「凡事皆可为」精神。迎接新学年,香港科大于9月2日起举行为期两天的开学嘉年华「Fire Up Your Year」,校长叶玉如教授联同一众…

AI写作保姆级方法论第六节-AI的终极调教心法(问题+解决方案)

效果是什么 大象基于大量的实战经验,总结出了AI prompt调教的终极杀手锏:【终极调教心法:1个原则和3个技巧】 一个原则,是指AI的【角色扮演法】,openai官方基于AI原理给出的让AI听话的技巧。所有AI的使用玩法&#xff…

Leetcode3250. 单调数组对的数目 I

Every day a Leetcode 题目来源:3250. 单调数组对的数目 I 解法1:记忆化搜索 题目输入一个数组nums。 假设有两个数组A和B,A递增,B递减,且 Ai Bi numsi ​ 问有多少对(A,B)数组对。 解法: 代码&…

java基础知识-JVM知识详解

一、JVM内存结构 Java虚拟机(JVM)的内存结构主要分为几个不同的区域,每个区域都有其特定的目的和功能。以下是JVM内存结构的主要组成部分: 先看一下总体的结构图 程序计数器(Program Counter Register) 这是一个较小的内存块,用于存储当前线程所执行的字节码指令的地址…

第T4周:猴痘病识别

本文为🔗365天深度学习训练营 中的学习记录博客原作者:K同学啊 我的环境: ● 语言环境:Python3.6.5 ● 编译器:jupyter notebook ● 深度学习框架:TensorFlow 2.6.2 ● 数据:猴痘病数据集 一、…

非 congda 环境 ubuntu 22.04 源码编译安装 pytorch 并初步检查可用性

非 congda 环境 编译安装 pytorch 0, 安装 cuda sdk ,cudnn 及 nccl 按照官网步骤,blacklist需要特别注意 0.1 cuda sdk 0.2 cudnn 0.3 安装nccl git clone --recursive https://github.com/NVIDIA/nccl.git ls cd nccl/ make -j src.build sudo apt…

使用 docker 部署 kvm 图形化管理工具 WebVirtMgr

文章目录 [toc]前提条件镜像构建启动 webvirtmgr创建其他 superuser配置 nginx 反向代理和域名访问绑定 kvm 宿主机local sockettcp 连接 虚拟机创建创建快照虚拟机克隆删除虚拟机 kvm 官方提供了以下这些图形化管理,license 这块也提示了是商业版(Comme…

rometheus Blackbox监控网站

Blackbox Exporter简介 blackbox_exporter 是 Prometheus 拿来对 http/https、tcp、icmp、dns、进行的黑盒监控工具,也就是从服务、主机等外部进行探测,来查看服务、主机等是否可用。 Blackbox Exporter 默认端口是 9115, 安装1 wget htt…

Codeforces Round (Div.3) C.Sort (前缀和的应用)

原题: time limit per test:5 seconds memory limit per test:256 megabytes You are given two strings a and b of length n. Then, you are (forced against your will) to answer q queries. For each query, you are given a range …

Dify 与 FastGPT 流程编排能力对比分析

Dify 与 FastGPT 流程编排能力对比分析 一、引言 在人工智能快速发展的今天,大语言模型(LLM)应用平台正在重塑各行各业的工作流程。其中,Dify 和 FastGPT 作为两款具有重要影响力的工具,凭借各自独特的流程编排能力&a…

智能化升级:AI在客服知识库中的应用

引言 在数字化时代,客户服务已成为企业竞争的关键一环。随着人工智能(AI)技术的飞速发展,传统客服模式正经历着前所未有的变革。AI与客服知识库的深度融合,不仅极大地提升了客服处理的效率与准确性,还为用…

unreal engine 5.4.4 runtime 使用PCG

Unreal PCG Runtime runtime环境下控制PCG PCG Graph 这里简单的在landscape上Spawn Static Mesh 和 Spawn Actor GraphSetting 自定义的参数,方便修改 场景 这里新建了一个蓝图Actor PCG_Ctrl, 用来runtime的时候控制PCG生成 Construct 获取场景中的PCGVolum…

Oracle版本简介手册

Oracle版本简介手册 图1—数据库发布路线图表 Oracle数据库的各个版本反映了其技术的发展历程和功能增强,从最早的Oracle 1(1979年)到最新的版本,每个版本都带来了新的特性和改进,以满足不断变化的企业需求。以下是Or…

【数学建模国赛思路预约】2024全国大学生数学建模竞赛助攻思路、代码、论文

2024年全国大学生数学建模大赛马上就要开始了,大家有没有准备好呢,今年将会和之前一样,将会在比赛赛中时期为大家提供比赛各题的相关解题思路、可运行代码参考以及成品论文。 一、分享计划表如下所示 1、 赛中分享内容包括(2023国…

详解React setState调用原理和批量更新的过程

1. React setState 调用的原理 setState目录 1. React setState 调用的原理2. React setState 调用之后发生了什么?是同步还是异步?3. React中的setState批量更新的过程是什么? 具体的执行过程如下(源码级解析)&#x…

马尔科夫决策过程(MDP):详解与应用

马尔科夫决策过程(MDP):详解与应用 引言 在人工智能、机器学习和运筹学等领域,马尔科夫决策过程(Markov Decision Process,MDP)是一个基础而重要的数学模型。MDP 被广泛应用于优化决策问题&am…

1.1什么是SQL注入

SQL 注入(Injection) 概述 SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来…

异步 “一发入魂“

异步 概述: 异步就是从主线程发射一个子线程来完成任务。 什么时候用异步编程 主线程作为一个线程,不能够同时接受多方面的请求。所以,当一个事件没有结束时,界面将无法处理其他请求。 为了避免这种情况的发生,我们…

zookeeper是啥?在kafka中有什么作用

一、Zookeeper是啥 问AI,它是这么说: ZooKeeper是一个开源的分布式协调服务。 ZooKeeper最初由雅虎研究院开发,用于解决大型分布式系统中的协调问题,特别是为了避免分布式单点故障。它被设计成一个简单易用的接口集,封…