JVM垃圾回收机制

JVM 可达性分析法

1. 垃圾回收器的基本概念

什么是垃圾回收器:JVM 为 Java 提供了垃圾回收机制,其实是一种偏自动的内存管理机制。简单来说,垃圾回收器会自动追踪所有正在使用的对象,并将其余未被使用的对象标记为垃圾,不需要开发者手动进行垃圾回收,JVM 自动进行垃圾回收,释放内容。

为什么进行垃圾回收:如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收。除非内存无限大,我们可以任性的分配不回收,但是事实并非如此。所以,垃圾回收是必须的。

哪些内存需要回收:哪些内存需要回收是垃圾回收机制第一个要考虑的问题,所谓“要回收的垃圾”无非就是那些不可能再被任何途径所使用的对象。无需再使用的对象,会被标记为垃圾,等待JVM回收此部分内存。

Tips:Java中通过可达性分析法来检测对象是否为垃圾,如果不可达,则将对象标记为垃圾,会被 JVM 回收,接下来我们学习可达性分析法。

2. 可达性分析法基本原理

方法原理:通过一系列称为"GC Roots"的对象作为起始点,从这些节点向下搜索,搜索所走过的路径称为引用链(即GC Roots到对象不可达时),则证明此对象是不可用的。

那么问题又来了,如何选取 GCRoots 对象呢?在 Java 语言中,可以作为 GCRoots 的对象包括下面几种:

  • 虚拟机栈(栈帧中的局部变量区,也叫局部变量表)中引用的对象;
  • 方法区中的类静态变量属性引用的对象;
  • 方法区中常量引用的对象;
  • 本地方法栈中 JNI(Native方法)引用的对象。

Tips:看了如上的原理与 GC Roots 选择的描述,感觉概念性问题比较抽象,难于理解,我们继续通过示例来进一步理解可达性分析法。

3. 可达性分析法示例

上文中提到了,可达性分析法是通过 GC Roots 为起点的搜索,有四种对象可以作为 GC Roots,那么我们通过如下示意图来理解下,何为不可达对象。

在这里插入图片描述

GC Roots 四种类型解释:从上图中,我们可以看到四种 GC Roots。这里我们对这四种 GC Roots 做一下更为细致的解释。

  • 虚拟机栈中的引用的对象:我们在程序中正常创建一个对象,对象会在堆上开辟一块空间,同时会将这块空间的地址作为引用保存到虚拟机栈中,如果对象生命周期结束了,那么引用就会从虚拟机栈中出栈,因此如果在虚拟机栈中有引用,就说明这个对象还是有用的,这种情况是最常见的;
  • 全局的静态的对象:也就是使用了 static 关键字,由于虚拟机栈是线程私有的,所以这种对象的引用会保存在共有的方法区中,显然将方法区中的静态引用作为 GC Roots 是必须的;
  • 常量引用:就是使用了 static final 关键字,由于这种引用初始化之后不会修改,所以方法区常量池里的引用的对象也应该作为 GC Roots;
  • Native 方法引用对象:这一种是在使用 JNI 技术时,有时候单纯的 Java 代码并不能满足我们的需求,我们可能需要在 Java 中调用 C 或 C++ 的代码,因此会使用 native 方法,JVM 内存中专门有一块本地方法栈,用来保存这些对象的引用,所以本地方法栈中引用的对象也会被作为 GC Roots。

从上图来理解可达性分析法就会非常简单,四种 GC Roots 无非是 Java 中的引用对象,从GC Roots 出发,类似于我们使用开发工具看代码,发现某部分代码用不到了,我们就会删除这部分代码。其实可达性分析法也是如此,发现某些对象不可达了,就会被垃圾回收器收集。

从上图中来看,对象 A,B,C,D,E,F 为可达对象;而对象 G,H,I,J,K 为不可达对象,会被标记为垃圾对象,最终被垃圾回收器回收。

JVM 四种引用

1. 可达性分析的四种引用类型

上节内容讲解了可达性分析,可达性分析的 GC Roots 均为引用对象,那么引用对象有 4 种引用类型如下:

  • 强引用
  • 软引用
  • 弱引用
  • 虚引用

2. 强引用

定义:强引用就是指在程序代码之中普遍存在的,类似Object obj = new Object()这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。当内存空间不足,Java 虚拟机宁愿抛出 OutOfMemoryError 错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

代码示例

public class DemoTest {public static void main(String[] args) {Object obj = new Object(); // 强引用}
}
代码块12345

在强引用的定义中有这样一句话:“只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。” 那么有没有办法将强引用消除呢?

消除强引用示例代码

public class DemoTest {public static void main(String[] args) {Object obj = new Object(); // 强引用obj = null; //消除强引用}
}

如果不使用强引用时,可以赋值 obj=null,显示的设置 obj 为 null,则 gc 认为该对象不存在引用,这时候就可以回收此对象。

3. 软引用

定义:软引用用来描述一些还有用,但并非必需的对象。对于软引用关联着的对象,如果内存充足,则垃圾回收器不会回收该对象,如果内存不够了,就会回收这些对象的内存。

在 JDK 1.2 之后,提供了 SoftReference 类来实现软引用。软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

软引用使用场景:Android 应用图片
软引用主要应用于内存敏感的高速缓存,在 Android 系统中经常使用到。一般情况下,Android 应用会用到大量的默认图片,这些图片很多地方会用到。如果每次都去读取图片,由于读取文件需要硬件操作,速度较慢,会导致性能较低。所以我们考虑将图片缓存起来,需要的时候直接从内存中读取。

但是,由于图片占用内存空间比较大,缓存很多图片需要很多的内存,就可能比较容易发生 OutOfMemory 异常。这时,我们可以考虑使用软引用技术来避免这个问题发生。

SoftReference 可以解决 OOM 的问题,每一个对象通过软引用进行实例化,这个对象就以cache的形式保存起来,当再次调用这个对象时,那么直接通过软引用中的 get() 方法,就可以得到对象中的资源数据,这样就没必要再次进行读取了,直接从 cache 中就可以读取得到,当内存将要发生 OOM 的时候,GC 会迅速把所有的软引用清除,防止 OOM 发生。

4. 弱引用

定义:弱引用描述非必需对象。被弱引用关联的对象只能生存到下一次垃圾回收之前,垃圾收集器工作之后,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。Java 中的类 WeakReference 表示弱引用。

代码示例

import java.lang.ref.WeakReference;public class Main {public static void main(String[] args) {    WeakReference<String> sr = new WeakReference<String>(new String("hello"));         System.out.println(sr.get());System.gc();                //通知JVM的gc进行垃圾回收System.out.println(sr.get());}
}

结果验证:第二个输出结果是 null,这说明只要 JVM 进行垃圾回收,被弱引用关联的对象必定会被回收掉。

hello
null

5. 虚引用

定义:"虚引用"顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。虚引用在 Java 中使用 java.lang.ref.PhantomReference 类表示。

作用:虚引用主要用来跟踪对象被垃圾回收的活动。

虚引用与软引用和弱引用的区别:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

使用示例:虚引用必须和引用队列(ReferenceQueue)联合使用

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class Main {public static void main(String[] args) {ReferenceQueue<String> queue = new ReferenceQueue<String>();PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue);System.out.println(pr.get());}
}

JVM 常见的垃圾回收算法

1. 垃圾回收算法种类

我们先来讨论一个问题,垃圾回收算法有几种?

如果单纯从一些博客或者论坛上的内容来说,部分作者会将垃圾回收分为如下 4 种算法:

  • 标记-清除(Mark-Sweep)算法;
  • 复制(coping)算法;
  • 标记-整理(Mark-Compact)算法;
  • 分代收集算法。

但是这种分类是不准确的,准确来说,垃圾回收只有 3 种算法:

  • 标记-清除(Mark-Sweep)算法;
  • 复制(coping)算法;
  • 标记-整理(Mark-Compact)算法。

为什么会有所谓的“分代收集算法”呢? 此处我们埋下一个伏笔,后文中我会在适当的地方给予解释。

2. 标记-清除(Mark-Sweep)算法

标记 - 清除(Mark-Sweep)算法是最基本的算法。

基本概念:标记-清除算法就如同它的名字一样,分为“标记”和“清除”两个阶段:

  • 首先标记出所有需要回收的对象,这就是标记阶段;
  • 标记完成后统一回收所有被标记的对象,这就是所谓的清除阶段。

缺点:这种算法的不足主要体现在效率和空间。

  • 从效率的角度讲:标记和清除两个过程的的效率都不高;
  • 从空间的角度讲:标记清楚后会产生大量不连续的内存碎片,内存碎片太多可能会导致以后程序运行过程中在需要分配较大对象时,无法找到足够的连续内存而不得不提前触发一次垃圾回收动作。

为了更加透彻的理解标记-清除(Mark-Sweep)算法,我们来看下如下示意图,通过直观的图形展示,彻底搞懂标记-清除(Mark-Sweep)算法。

在这里插入图片描述

3. 复制(coping)算法

Tips:前文提到过,标记-清除(Mark-Sweep)算法从效率的角度讲,"标记"和"清除"两个过程的的效率都不高,为了提升效率,我们引出了复制(coping)算法。

基本概念:复制算法是为了解决效率问题而出现的,它将可用的内存分为两块,每次只用其中的一块,当这一块内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已经使用过的内存一次性清理掉。这样每次只需要对整个半区进行内存回收,内存分配的执行过程如下图所示:

在这里插入图片描述

缺点:不过这种算法有个缺点,内存缩小为原来的一半,这样代价太高了。

现在的商用模拟机都采用这种算法来回收新生代,不过研究表明1:1的比例非常不科学,因此新生代的内存被划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。

每次回收时,将Eden和Survivor中还存活着的对象一次性复制到另外一块Survivor空间上,最后清理掉Eden和刚才使用过的Survivor空间。

HotSpot虚拟机默认Eden区和Survivor区的比例为8:1,意思是每次新生代中可用内存空间为整个新生代容量的90%。当然,我们没有办法保证每次回收都只有不多于10%的对象存活,当Survivor空间不够用时,需要依赖老年代进行分配担保(Handle Promotion)。

4. 标记-整理(Mark-Compact)算法

Tips:复制算法在对象存活率较高的场景下要进行大量的复制操作,效率还是很低。并且每次只使用一半的内存空间,资源浪费严重。标记-整理(Mark-Compact)算法解决了内存利用率的问题,并且减少了大量复制的问题。

根据老年代的特点,有人提出了另外标记-整理(Mark-Compact)算法,标记过程与标记-整理(Mark-Compact)算法一样,不过不是直接对可回收对象进行整理,而是让所有存活对象都向一端移动,然后清理掉边界以外的内存。标记-整理算法的工作过程如图:

在这里插入图片描述

5. 分代收集

问题:我们上文埋下了伏笔,分代清理到底是不是第四种算法呢?

解答:不是,我们通常称之为分代收集理论,或称之为分代收集思想。目前虚拟机基本都采用分代收集理论来进行垃圾回收。

分代收集理论结合了以上的 3 种算法,根据对象的生命周期的不同将内存划分为几块,然后根据各块的特点采用最适当的收集算法。准确的说,分代收集理论就是在不同的内存区域使用不同的算法,它是以上 3 种算法的使用者。

因此说,分代清理并非是一种单独的算法,而是一种收集理论。

在这里插入图片描述

MinorGC、MajorGC、FullGC垃圾回收介绍

MinorGC (新生代垃圾回收)

在这里插入图片描述

JDK1.8 堆内部结构

从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC,也叫Young GC。因为Java对象大多具备朝生夕死的特征,所以MinorGC非常频繁,一般回收速度也比较快。一般采用复制算法。

说明:Minor GC可能会引发STW,暂停其他用户的线程,需要等JVM垃圾回收结束后,用户线程才恢复运行。

Minor GC 触发条件

  • Eden伊甸园区满了
  • 新new的对象需要分配到新生代的Eden伊甸园区,当Eden区的空间不够的时候需要进行MinorGC策略回收,

Major GC(老年代垃圾回收)

Major GC指发生在老年代的GC。

Major GC触发条件

老年代空间不足时,会先尝试触发Minor GC。Minor GC之后空间还不足,则会触发Major GC。

说明:发生在老年代的GC ,基本上进行一次Major GC 就会伴随进行一次 Minor GC。Major GC 的速度一般会比 Minor GC 慢 10 倍,并且STW的时间更长。

Full GC (新生代+老年代垃圾回收)

Full GC可以理解为Major GC+Minor GC组合后进行的一整个过程,是清理JVM整个堆空间(年轻代和老年代空间)。

Full GC触发条件

  • 调用System.gc()方法时,可通过-XX:+ DisableExplicitGC 参数来禁止调用System.gc()
  • 当方法区空间不足时
  • Minor GC后存活的对象大小超过了老年代剩余空间
  • Minor GC时中Survivor幸存区空间不足时,判断是否允许担保失败,不允许则触发Full GC。允许,并且每次晋升到老年代的对象平均大小>老年代最大可用连续内存空间,也会触发Full GC
  • CMS GC异常,CMS运行期间预留的内存无法满足程序需要,就会出现一次“Concurrent Mode Failure”失败,会触发Full GC

STW(Stop The World):垃圾回收发生过程中,会产生应用程序的停顿现象。停顿产生的时候整个应用程序线程都会被暂停,有点应用程序像卡死的情况。

JVM 垃圾回收器分类

1. 前言

本节主要讲解 7 种垃圾回收器,其中有 3 种垃圾回收器是作用于年轻代垃圾回收的收集器;另外 3 种圾回收器是作用于老年代垃圾回收的收集器;剩余的 1 种垃圾回收器能够同时作用于年轻代和老年代。

7 种垃圾回收器以及其作用的内存区域如下图所示:

在这里插入图片描述

2. Serial收集器

基本概念:Serial收集器是最基本、发展历史最久的收集器,这个收集器是采用复制算法的单线程的收集器。

Tips:从概念上来看,我们需要注意Serial收集器的两个特点:一个是采用复制算法,另外一个是单线程收集。

单线程的收集器:单线程一方面意味着他只会使用一个 CPU 或者一条线程去完成垃圾收集工作,另一方面也意味着他进行垃圾收集时必须暂停其他线程的所有工作,直到它收集结束为止。

不过实际上到目前为止,Serial收集器依然是虚拟机运行在 Client 模式下的默认新生代收集器,因为它简单而高效。Serial 收集器运行过程如下图所示:

在这里插入图片描述

3. Parnew收集器

基本概念:Parnew 收集器其实就是Serial收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为和 Serial 收集器完全一样,但是他却是 Server 模式下的虚拟机首选的新生代收集器。

Tips:从概念上来看,我们需要注意Parnew收集器的两个特点:一个是采用复制算法,另外一个是多线程收集。

特点

  • 除了 Serial 收集器外,目前只有它能与 CMS 收集器配合工作。CMS 收集器第一次实现了让垃圾收集器与用户线程基本上同时工作;
  • Parnew 收集器默认开启的收集线程数与 CPU 数量相同,在 CPU 数量非常多的情况下,可以使用 -XX:ParallelGCThreads 参数来限制垃圾收集的线程数。

Parnew 收集器运行过程如图所示:

在这里插入图片描述

4. Parallel Scavenge收集器

基本概念:Parallel Scavenge 收集器也是一个新生代收集器,也采用了复制算法,也是并行的多线程收集器。Parallel Scavenge 收集器的目标是达到一个可控制的吞吐量。Parallel Scavenge 收集器是虚拟机运行在 Server 模式下的默认垃圾收集器。被称为“吞吐量优先收集器”。

Tips:从概念上来看,我们需要注意Parallel Scavenge收集器的三个个特点:一个是采用复制算法,一个是多线程收集,一个是达到控制吞吐量的目标。

Parallel Scavenge 收集器运行过程同 Parnew 收集器一样:

在这里插入图片描述

控制吞吐量:CMS 等收集器的关注点是尽可能缩短垃圾收集时用户线程的停顿时间,而 Parallel Scavenge 收集器的目标则是达到一个可控制的吞吐量。所谓吞吐量就是 CPU 用于运行用户代码时间与 CPU 总消耗时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)

空间吞吐量参数介绍:虚拟机提供了-XX:MaxGCPauseMills-XX:GCTimeRatio 两个参数来精确控制最大垃圾收集停顿时间和吞吐量大小。不过不要以为前者越小越好,GC 停顿时间的缩短是以牺牲吞吐量和新生代空间换取的。由于与吞吐量关系密切,Parallel Scavenge 收集器也被称为“吞吐量优先收集器”。

Parallel Scavenge 收集器有一个参数 -XX:UseAdaptiveSizePolicy 参数,这是一个开关参数,这个参数打开之后,就不需要手动指定新生代大小、Eden 区和 Survivor 参数等细节参数了,虚拟机会根据当前系统的运行情况以及性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量。

如果对于垃圾收集器运作原理不太了解,以至于在优化比较困难的时候,可以使用 Parallel Scavenge收集器配合自适应调节策略,把内存管理的调优任务交给虚拟机去完成。

5. Serial Old收集器

基本概念: Serial Old 收集器同样是一个单线程收集器,作用于老年代,使用“标记-整理算法”,这个收集器的主要意义也是在于给 Client 模式下的虚拟机使用。

Serial Old 收集器运行过程如图所示:

在这里插入图片描述

6. Parallel Old收集器

基本概念: Parallel Old 收集器是 Parallel Scavenge 收集器的老年代版本,使用多线程和“标记-整理算法”进行垃圾回收。

这个收集器在 JDK 1.6 之后的出现,“吞吐量优先收集器”终于有了比较名副其实的应用组合,在注重吞吐量以及 CPU 资源敏感的场合,都可以优先考虑 Parallel Scavenge收集器+Parallel Old收集器 的组合。

Parallel Scavenge 收集器+Parallel Old 收集器 的组合运行过程如下图所示:

在这里插入图片描述

7. CMS收集器

基本概念:CMS(Conrrurent Mark Sweep,连续标记扫描)收集器是以获取最短回收停顿时间为目标的收集器。使用标记-清除算法。

收集步骤:收集过程分为如下四步:

  • 初始标记:标记 GCRoots 能直接关联到的对象,时间很短;
  • 并发标记:进行 GCRoots Tracing(可达性分析)过程,时间很长;
  • 重新标记:修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,时间较长;
  • 并发清除:回收内存空间,时间很长。其中,并发标记与并发清除两个阶段耗时最长,但是可以与用户线程并发执行。

CMS 收集器运行过程如下图所示:

在这里插入图片描述

8. G1收集器

基本概念:G1 是目前技术发展的最前沿成果之一,HotSpot开发团队赋予它的使命是未来可以替换掉 JDK1.5 中发布的 CMS 收集器。

与其他GC收集器相比,G1收集器具有以下特点

  • 并发和并行:使用多个 CPU 来缩短 Stop The World 停顿时间,与用户线程并发执行;
  • 分代收集:独立管理整个堆,但是能够采用不同的方式去处理新创建对象和已经存活了一段时间、熬过多次 GC 的旧对象,以获取更好的收集效果;
  • 空间整合:基于标记-整理算法,无内存碎片产生;
  • 可预测的停顿:能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在垃圾收集器上的时间不得超过N毫秒。

在G1之前的垃圾收集器,收集的范围都是整个新生代或者老年代,而 G1 不再是这样。使用 G1 收集器时,Java 堆的内存布局与其他收集器有很大差别,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分(可以不连续)Region 的集合。

9. 小结

本节主要讲解了 7 种垃圾收集器:Serial 收集器,Parnew 收集器,Parallel Scavenge 收集器,Serial Old 收集器,Parallel Old 收集器,CMS 收集器和G1 收集器。

其中专门针对年轻代的收集器有 Serial 收集器,Parnew 收集器和 Parallel Scavenge 收集器;专门作用于老年代的收集器有Serial Old 收集器,Parallel Old 收集器和 CMS 收集器;而 G1 收集器即能够作用于年轻代,也能够作用于老年代。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IntelliJ Idea 撤回git已经push的操作

最初的样子 现在的样子 解决方案 第一步&#xff0c;commit到本地撤回&#xff1a; 打开提交历史记录&#xff0c;选中回退的版本右键&#xff0c;点击“Reset Current Branch to Here…”,然后选中“Mixed”&#xff0c;点击Reset后&#xff0c;之前commit的代码会在本地显…

【Proteus仿真】【Arduino单片机】LCD1602-IIC液晶显示

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用PCF8574、LCD1602液晶等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602液晶显示各种效果。 二、软件设计 /* 作者&#xff1a;嗨小…

STM32笔记—EXTI外部中断

一、简介 中断&#xff1a;在主程序运行过程中&#xff0c;出现了特定的中断触发条件&#xff08;中断源&#xff09;&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理中断程序&#xff0c;处理完成后又返回原来被暂停的位置继续运行&#xff1b; 中断优先级&…

线程池创建、执行、销毁的原理解析

目录 线程池的执行原理线程执行参考&#xff1a; 线程池的执行原理 假设最大核心数是2&#xff0c;非核心线程数为1&#xff0c;队列长度是3 来第一个任务的时候&#xff0c;没有工作线程在工作&#xff0c;需要创建一个 来第二个任务的时候&#xff0c;发现当前核心线程数…

Win10共享打印机,别人连接不上出现无法连接到打印机错误码0x0000011b

环境&#xff1a; Win10 专业版 惠普L1119 问题描述&#xff1a; Win10共享打印机&#xff0c;别人连接不上出现无法连接到打印机错误码0x0000011b 解决方案&#xff1a; 1.打开我这台电脑的注册表找到 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Print在右侧…

牛客出bug(华为机试HJ71)

Hj71&#xff1a;字符串通配符 描述 问题描述&#xff1a;在计算机中&#xff0c;通配符一种特殊语法&#xff0c;广泛应用于文件搜索、数据库、正则表达式等领域。现要求各位实现字符串通配符的算法。 要求&#xff1a; 实现如下2个通配符&#xff1a; *&#xff1a;匹配0个…

Vue 组件化编程 和 生命周期

目录 一、组件化编程 1.基本介绍 : 2.原理示意图 : 3.全局组件示例 : 4.局部组件示例 : 5.全局组件和局部组件的区别 : 二、生命周期 1.基本介绍 : 2.生命周期示意图 : 3.实例测试 : 一、组件化编程 1.基本介绍 : (1) 开发大型应用的时候&#xff0c;页面往往划分成…

Java用Jsoup库实现的多线程爬虫代码

因为没有提供具体的Python多线程跑数据的内容&#xff0c;所以我们将假设你想要爬取的网站是一个简单的URL。以下是一个基本的Java爬虫程序&#xff0c;使用了Jsoup库来解析HTML和爬虫ip信息。 import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nod…

开设自己的网站系类01购买服务器

开始建设自己的网站吧&#xff01; 编者买了一个服务器打算自己构建一个网站&#xff0c;用于记录生活。网站大概算是一个个人博客吧。记录创建过程的一些步骤 要开设自己的网站&#xff0c;需要执行以下关键步骤 以下只是初步列出了建立自己的网站的大概步骤&#xff0c;后…

【PHP网页应用】MySQL数据库增删改查 基础版

使用PHP编写一个简单的网页&#xff0c;实现对MySQL数据库的增删改和展示操作 页面实现在index.php&#xff0c;其中basic.php为没有css美化的原始人版本 函数实现在database.php 目录 功能基本实现版 CSS美化版 basicindex.php index.php database.php 代码讲解 功能基…

2023年9月少儿编程 中国电子学会图形化编程等级考试Scratch编程二级真题解析(选择题)

2023年9月scratch编程等级考试二级真题 选择题(共25题,每题2分,共50分) 1、点击绿旗,运行程序后,舞台上的图形是 A、画笔粗细为4的三角形 B、画笔粗细为5的六边形 C、画笔粗细为4的六角形 D、画笔粗细为5的三角形 答案:D 考点分析:考查积木综合使用,重点考查画笔…

数字滤波器分析---频率响应

数字滤波器分析---频率响应 幅值、相位、冲激和阶跃响应、相位和群延迟、零极点分析。 分析滤波器的频域和时域响应。可视化复平面中的滤波器极点和零点。 频率响应 数字域 freqz 使用基于 FFT 的算法来计算数字滤波器的 Z 变换频率响应。具体来说&#xff0c;语句 [h,w]…

如何构建并提高自己的核心竞争力?

上一篇文章聊到了软件工程师的核心竞争力主要分为三个方面&#xff1a;快速学习能力、解决问题能力和个人影响力&#xff0c;且核心竞争力的培养和提高需要长时间实践和积累&#xff0c;并不是短时间就可以达到的。这篇文章&#xff0c; 来聊聊如何培养和提高自己的核心竞争力。…

2023年云计算发展趋势浅析

​​​​​​​ 云计算的概念 云计算是一种通过互联网提供计算资源和服务的模式。它允许用户通过网络访问和使用共享的计算资源&#xff0c;而无需拥有或管理这些资源的物理设备。云计算的核心理念是将计算能力、存储资源和应用程序提供给用户&#xff0c;以便随时随地根据需要…

线性代数(二)| 行列式性质 求值 特殊行列式 加边法 归纳法等多种方法

文章目录 1. 性质1.1 重要性质梳理1.1.1 转置和初等变换1.1.2加法行列式可拆分1.1.3 乘积行列式可拆分 1.2 行列式性质的应用1.2.1 简化运算1.2.2 将行列式转换为&#xff08;二&#xff09;中的特殊行列式 2 特殊行列式2.1 上三角或下三角行列式2.2 三叉行列式2.3 行列式行和&…

【Linux】第十三站:进程状态

文章目录 一、进程状态1.运行状态2.阻塞状态3.挂起状态 二、具体Linux中的进程状态1.Linux中的状态2.R状态3.S状态4.D状态5.T、t状态6.X状态(dead)7.Z状态&#xff08;zombie&#xff09;8.僵尸进程总结9.孤儿进程总结 一、进程状态 在我们一般的操作系统学科中&#xff0c;它…

Linux学习第39天:Linux I2C 驱动实验(三):哥俩好

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 linux I2C驱动试验整节的思维导图如下&#xff1a; 本节笔记主要学习试验程序的编写及运行测试。其中试验程序的编写主要包括修改设备树、AP3216驱动编写及编写测…

rocksdb 中 db_bench 的使用方法

硬件要求 硬件要求如表1所示。 表1 硬件要求 项目 说明 CPU 12 * AMD Ryzen 5 5500U with Radeon Graphics 内存 DDR4 磁盘 HDD 软件要求 软件要求如表2所示。 表2 软件要求 项目 版本 说明 下载地址 CentOS 7.6 操作系统。 Download kernel 4.14.0 内核。…

pytorch优化器详解

1 什么是优化器 1.1 优化器介绍 在PyTorch中&#xff0c;优化器&#xff08;Optimizer&#xff09;是用于更新神经网络参数的工具。它根据计算得到的损失函数的梯度来调整模型的参数&#xff0c;以最小化损失函数并改善模型的性能。 即优化器是一种特定的机器学习算法&#…

磁盘的分区、格式化、检验与挂载 ---- fdisk,mkfs,mount

磁盘的分区、格式化、检验与挂载 磁盘管理是非常重要的&#xff0c;当我们想要再系统里面新增一块磁盘使用时&#xff0c;应执行如下几步&#xff1a; 对磁盘进行划分&#xff0c;以建立可用的硬盘分区 &#xff08;fdisk / gdisk&#xff09;对硬盘分区进行格式化&#xff0…