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

【JVM】垃圾回收(GC)详解

垃圾回收(GC)详解

  • 一. 死亡对象的判断算法
    • 1. 引用计数算法
    • 2. 可达性分析算法
  • 二. 垃圾回收算法
    • 1. 标记-清除算法
    • 2. 复制算法
    • 3. 标记-整理算法
    • 4. 分代算法
  • 三. STW
    • 1. 为什么要 STW
    • 2. 什么情况下 STW
  • 四. 垃圾收集器
    • 1. CMS收集器(老年代收集器,并发GC)
    • 2. G1收集器(唯一一款全区域的垃圾回收器)
  • 总结:一个对象的一生

垃圾回收 (Garbage Collection)的区域:

对于程序计数器、虚拟机栈、本地方法栈而言,其生命周期与相关线程有关,随线程而生,随线程而灭。并且这三个区域的内存分配与回收具有确定性,当方法结束或者线程结束时,内存就自然跟着线程回收了。对于方法区,是类加载时使用的,类卸载时释放,但是类卸载操作是一个非常低频的操作。所以内存分配和回收主要关注的是堆这个区域。

Java 堆中存放着几乎所有的对象实例,垃圾回收器在对堆进行垃圾回收前,首先要判断这些对象哪些还存活,哪些已经"死去"。

一. 死亡对象的判断算法

1. 引用计数算法

引用计数描述的算法为:

  • 给对象增加一个引用计数器;
  • 每当有一个地方引用它时,计数器就+1;当引用失效时,计数器就-1;
  • 任何时刻计数器为 0 的对象就是不能再被使用的,即对象已"死"。

引用计数法实现简单,判定效率也比较高,在大部分情况下都是一个不错的算法。

缺点:

  1. 空间利用率低, 每个对象都得搭配一个计数器,如果对象本身比较大,多出 4 个字节不算啥,但是如果对象本身就很小,比如 4 个字节,再加上计数器,相当于浪费了一半的空间。
  2. 有循环引用问题。

观察循环引用问题

class Test {public Object instance = null;public static void testGC() {Test test1 = new Test();Test test2 = new Test();test1.instance = test2;test2.instance = test1;test1 = null;test2 = null;}
}

test1、test2 两个对象的引用计数器都不为 0, 但是其实 test1 和 test2 都是无法被外界代码访问到的。

2. 可达性分析算法

Java并不采用引用计数法来判断对象是否已"死",而采用"可达性分析"来判断对象是否存活。

此算法的核心思想为 :

  • 通过一系列称为"GC Roots"的对象作为起始点,
  • 从这些节点开始向下搜索,搜索走过的路径称之为"引用链",
  • 当一个对象到 GC Roots 没有任何的引用链相连时(从GC Roots到这个对象不可达)时,证明此对象是不可用的。

以下图为例:

在这里插入图片描述

对象Object5-Object7之间虽然彼此还有关联,但是它们到GC Roots是不可达的,因此他们会被判定为可回收对象。

在Java语言中,可作为GC Roots的对象包含下面几种:

  1. 虚拟机栈(栈帧中的本地变量表)中引用的对象;
  2. 方法区中类静态属性引用的对象;
  3. 方法区中常量引用的对象;
  4. 本地方法栈中 JNI(Native方法)引用的对象。

优点:
克服了基于引用计数的两个缺点:空间利用率低和循环引用问题。

缺点:
系统开销大,遍历一次可能比较慢。

二. 垃圾回收算法

将死亡对象标记出来之后就可以进行垃圾回收操作了。

1. 标记-清除算法

"标记-清除"算法是最基础的收集算法。
算法分为"标记"和"清除"两个阶段 :

  • 首先标记出所有需要回收的对象;
  • 在标记完成后统一回收所有被标记的对象。

"标记-清除"算法的不足主要有两个 :

  1. 效率问题 : 标记和清除这两个过程的效率都不高
  2. 空间问题 : 标记清除后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行中需要分配较大对象时,无法找到足够连续内存而不得不提前触发另一次垃圾收集。

后续的收集算法都是基于这种思路并对其不足加以改进而已。

2. 复制算法

"复制"算法是为了解决 “标记-清理” 的内存碎片问题。

  • 它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块;
  • 当这块内存需要进行垃圾回收时,会将此区域还存活着的对象复制到另一块上面;
  • 然后再把已经使用过的内存区域一次清理掉。

这样做的好处是每次都是对整个半区进行内存回收,内存分配时也就不需要考虑内存碎片等复杂情况,只需要移动堆顶指针,按顺序分配即可。此算法实现简单,运行高效。

复制算法的缺点:

  1. 空间利用率低。
  2. 若要保留的对象比较多,要释放的对象少,此时复制开销就很大。

3. 标记-整理算法

复制收集算法在对象存活率较高时会进行比较多的复制操作,效率会变低。因此在老年代一般不能使用复制算法。
针对老年代的特点,提出了一种称之为"标记-整理算法"。标记过程仍与"标记-清除"过程一致,但后续步骤不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉端边界以外的内存。

在这里插入图片描述

注意:
标记整理算法也涉及到对象的复制,相比于复制算法,解决了空间利用率低的问题,但是仍然没有解决复制搬运元素开销大的问题。

虽然标记整理算法同样需要复制, 但是标记整理算法通常需要复制(移动)较少的对象,因为老年代的对象生命周期较长,一些对象在不同的垃圾回收周期中仍然存活,不需要频繁地移动。相比之下,复制算法在每次垃圾回收时都要复制大部分对象。

4. 分代算法

针对对象进行分类,(根据年龄划分)一个对象熬过一轮 GC 扫描成为涨了一岁,针对不同的对象,采用不同的方案。

新生代中使用复制算法,老年代中使用标记整理算法。

现在的商用虚拟机 (包括 HotSpot 都是采用复制算法来回收新生代)

  • 新生代中98%的对象都是"朝生夕死"的,所以并不需要按照1 : 1的比例来划分内存空间,而是将内存(新生代内存)分为一块较大的 Eden (伊甸园)空间和两块较小的 Survivor (幸存者)空间,
  • 每次使用 Eden 和其中一块Survivor(两个Survivor区域一个称为From区,另一个称为To区域)。
  • 当回收时,将 Eden 和 Survivor 中还存活的对象一次性复制到另一块 Survivor 空间上,最后清理掉 Eden 和刚才用过的 Survivor 空间。

在这里插入图片描述

当 Survivor 空间不够用时,需要依赖其他内存(老年代)进行分配担保。
HotSpot 默认 Eden 与 Survivor 的大小比例是8 : 1,也就是说 Eden:Survivor From : Survivor To = 8:1:1。
所以每次新生代可用内存空间为整个新生代容量的90%,而剩下的10%用来存放回收后存活的对象。

HotSpot实现的复制算法流程如下:

  1. 当 Eden 区满的时候,会触发第一次 Minor gc,把还活着的对象拷贝到 Survivor From 区;
    当 Eden 区再次触发 Minor gc 的时候,会扫描 Eden 区和 From 区域,对两个区域进行垃圾回收,经过这次回收后还存活的对象,则直接复制到 To 区域,并将 Eden 和 From 区域清空。
  2. 当后续 Eden 又发生 Minor gc 的时候,会对 Eden 和 To 区域进行垃圾回收,存活的对象复制到 From 区域,并将 Eden 和 To 区域清空。
  3. 部分对象会在 From 和 To 区域中复制来复制去,如此交换 15 次(由 JVM 参数 MaxTenuringThreshold 决定,这个参数默认是 15 ),最终如果还是存活,就存入到老年代。

基本经验规律:一个对象越老继续存活的可能性越大,(要死早死了),所以老年代的扫描频率远远低于新生代,老年代中使用标记整理的方式进行回收。

当前 JVM 垃圾收集都采用的是"分代收集(Generational Collection)"算法,这个算法并没有新思想,只是根据对象存活周期的不同将内存划分为几块。一般是把 Java 堆分为新生代和老年代。在新生代中,每次垃圾回收都有大批对象死去,只有少量存活,因此我们采用复制算法;而老年代中对象存活率高、没有额外空间对它进行分配担保,就必须采用"标记-清理"或者"标记-整理"算法。

哪些对象会进入新生代?哪些对象会进入老年代?

  • 新生代:一般创建的对象都会进入新生代;
  • 老年代:大对象和经历了 N 次(一般情况默认是 15 次)垃圾回收依然存活下来的对象会从新生代移动到老年代。(大对象拷贝开销比较大,不适合使用复制算法,直接进入老年代)

面试题 : 请问了解 Minor GC 和 Major GC 么,这两种 GC 有什么不一样吗?

  1. Minor GC 又称为新生代 GC : 指的是发生在新生代的垃圾收集。因为Java对象大多都具备朝生夕灭的特性,因此 Minor GC(采用复制算法)非常频繁,一般回收速度也比较快。
  2. Major GC 又称为 老年代 GC 或者 Full GC : 指发生在老年代的垃圾收集。出现了Major GC,经常会伴随至少一次的 Minor GC(并非绝对,在Parallel Scavenge收集器中就有直接进行 Full GC 的策略选择过程), 所以又称为 Full GC。Minor GC通常比Full GC频繁发生,因为新生代中的对象生命周期较短。Major GC的速度一般会比 Minor GC 慢10倍以上。

三. STW

STW(Stop-The-World)是垃圾回收中的一种现象,它表示在某些情况下,应用程序的所有线程都会被暂停,以便执行垃圾回收操作。STW 是为了确保垃圾回收器可以安全地执行清理和整理内存的工作,而不会受到应用程序线程的干扰。

1. 为什么要 STW

为了确保垃圾回收操作的正确性和安全性。尽管 STW 会导致应用程序线程的暂停,但它是必要的,因为在垃圾回收过程中需要满足以下条件:

  • 一致性:在执行垃圾回收期间,垃圾回收器需要准确地知道哪些对象是活动的,哪些是垃圾的。如果在执行垃圾回收时,应用程序线程仍然可以创建、修改或引用对象,那么垃圾回收器将无法确定对象的状态,可能会导致对象被错误地清理或保留。

  • 引用更新:在垃圾回收期间,垃圾回收器需要更新对象之间的引用关系,以确保引用的正确性。如果应用程序线程在垃圾回收期间继续运行,可能会导致引用关系混乱,垃圾回收器无法正确地更新引用。

  • 内存整理:在垃圾回收中,可能会发生内存整理操作,例如对象的移动,以减少内存碎片或提高内存利用率。如果应用程序线程继续操作内存,可能会导致内存整理的不一致性,从而破坏程序的状态。

  • 垃圾对象清理:STW 允许垃圾回收器安全地删除不再被引用的垃圾对象,而不会涉及到应用程序线程对这些对象的操作。

2. 什么情况下 STW

minor GC (新生代垃圾回收)和 major GC (老年代垃圾回收)都会触发 STW。

四. 垃圾收集器

垃圾收集器就是内存回收的具体实现。
垃圾收集器的作用:垃圾收集器是为了保证程序能够正常、持久运行的一种技术,它是将程序中不用的死亡对象也就是垃圾对象进行清除,从而保证了新对象能够正常申请到内存空间。

以下这些收集器是 HotSpot 虚拟机随着不同版本推出的重要的垃圾收集器:

在这里插入图片描述

上图展示了 7 种作用于不同分代的收集器,如果两个收集器之间存在连线,就说明他们之间可以搭配使用。
所处的区域,表示它是属于新生代收集器还是老年代收集器。在讲具体的收集器之前我们先来明确三个概念:

注意:这里的并行和并发只是指 GC 时的并行和并发。

  • 并行(Parallel) : 指多条垃圾收集线程并行工作,用户线程仍处于等待状态
  • 并发(Concurrent) : 指用户线程与垃圾收集线程同时执行(不一定并行,可能会交替执行),用户程序继续运行,而垃圾收集程序在另外一个CPU上。
  • 吞吐量:就是 CPU 用于运行用户代码的时间与 CPU 总消耗时间的比值。(可以简单理解为单位时间内回收的垃圾数量)

吞 吐 量 = 运 行 用 户 代 码 时 间 /(运 行 用 户 代 码 时 间 +垃 圾 收 集 时 间)

例如:虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%。

为什么会有这么多垃圾收集器?

自从有了 Java 语言就有了垃圾收集器,这么多垃圾收集器其实是历史发展的产物。

  • 最早的垃圾收集器为 Serial,也就是串行执行的垃圾收集器,Serial Old 为串行的老年代收集器,
  • 而随着时间的发展,为了提升更高的性能,于是有了 Serial 多线程版的垃圾收集器 ParNew。
  • 后来人们想要更高吞吐量 的垃圾收集器,吞吐量是指单位时间内成功回收垃圾的数量,于是就有了吞吐量优先的垃圾收集器 Parallel Scavenge(吞吐量优先的新生代垃圾收集器)和 Parallel Old(吞吐量优先的老年代垃圾收集器)。
  • 随着技术的发展后来又有了 CMS(Concurrent Mark Sweep)垃圾收集器,CMS 可以兼顾吞吐量和以获取最短回收停顿时间为目标的收集器,在 JDK 1.8(包含)之前 BS 系统的主流垃圾收集器,
  • 而在 JDK1.8 之后,出现了第一个既不完全属于新生代也不完全属于老年代的垃圾收集器 G1(Garbage First),G1 提供了基本不需要停止程序就可以收集垃圾的技术。

1. CMS收集器(老年代收集器,并发GC)

  • 特性:
    CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好的体验。CMS收集器就非常符合这类应用的需求。

CMS收集器是基于“标记—清除”算法实现的,它的运作过程相对于前面几种收集器来说更复杂一些,整个过程分为4个步骤:

  • 初始标记(CMS initial mark)
    初始标记仅仅只是标记一下 GC Roots 能直接关联到的对象,速度很快,需要 (STW)“Stop The World”。
  • 并发标记(CMS concurrent mark)
    并发标记阶段就是进行GC Roots Tracing 的过程。
  • 重新标记(CMS remark)
    重新标记阶段是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短,仍然需要“Stop The World”。
  • 并发清除(CMS concurrent sweep)
    并发清除阶段会清除对象。

由于整个过程中耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所以,从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。

优点:
CMS是一款优秀的收集器,它的主要优点在名字上已经体现出来了:并发收集、低停顿。
缺点:

  • CMS收集器对CPU资源非常敏感
    在并发阶段,它虽然不会导致用户线程停顿,但是会因为占用了一部分线程(或者说CPU资源)而导致应用程序变慢,总吞吐量会降低。

  • CMS收集器无法处理浮动垃圾
    CMS收集器无法处理浮动垃圾,可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生。
    由于CMS并发清理阶段用户线程还在运行着,伴随程序运行自然就还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在当次收集中处理掉它们,只好留待下一次GC时再清理掉。这一部分垃圾就称为“浮动垃圾”。
    也是由于在垃圾收集阶段用户线程还需要运行,那也就还需要预留有足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,需要预留一部分空间提供并发收集时的程序运作使用。
    要是 CMS 运行期间预留的内存无法满足程序需要,就会出现一次“Concurrent Mode Failure”失败,这时虚拟机将启动后备预案:临时启用 Serial Old 收集器来重新进行老年代的垃圾收集,这样停顿时间就很长了。

  • CMS收集器会产生大量空间碎片
    CMS 是一款基于“标记—清除”算法实现的收集器,这意味着收集结束时会有大量空间碎片产生。空间碎片过多时,将会给大对象分配带来很大麻烦,往往会出现老年代还有很大空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前触发一次 Full GC。

在这里插入图片描述

2. G1收集器(唯一一款全区域的垃圾回收器)

G1(Garbage First)垃圾回收器是用在 heap memory 很大的情况下,把heap划分为很多很多的 region 块,然后并行的对其进行垃圾回收。
G1垃圾回收器在清除实例所占用的内存空间后,还会做内存压缩。
G1垃圾回收器回收 region 的时候基本不会STW,而是基于 most garbage 优先回收(整体来看是基于"标记-整理"算法,局部(两个 region 之间)基于"复制"算法) 的策略来对 region 进行垃圾回收的。

在这里插入图片描述

一个region有可能属于Eden,Survivor 或者 Tenured 内存区域。图中的 E 表示该 region 属于 Eden 内存区域,S 表示属于 Survivor 内存区域,T 表示属于 Tenured 内存区域。图中空白的表示未使用的内存空间。
G1垃圾收集器还增加了一种新的内存区域,叫做 Humongous 内存区域,如图中的H块。这种内存区域主要用于存储大对象-即大小超过一个region 大小的50%的对象。

年轻代垃圾收集:
在 G1 垃圾收集器中,年轻代的垃圾回收过程使用复制算法。把 Eden 区和 Survivor 区的对象复制到新的 Survivor 区域。
如下图:

在这里插入图片描述

老年代垃收集

对于老年代上的垃圾收集,G1垃圾收集器也分为4个阶段,基本跟 CMS 垃圾收集器一样,但略有不同:

  • 初始标记(Initial Mark)阶段
    同CMS垃圾收集器的 Initial Mark 阶段一样,G1 也需要暂停应用程序的执行,它会标记从根对象出发,在根对象的第一层孩子节点中标记所有可达的对象。
    但是 G1 的垃圾收集器的 Initial Mark 阶段是跟 minor gc 一同发生的。也就是说,在 G1 中,你不用像在 CMS 那样,单独暂停应用程序的执行来运行 Initial Mark 阶段,而是在 G1 触发 minor gc 的时候一并将年老代上的 Initial Mark 给做了。
  • 并发标记(Concurrent Mark)阶段
    在这个阶段 G1 做的事情跟 CMS 一样。但 G1 同时还多做了一件事情,就是如果在 Concurrent Mark 阶段中,发现哪些 Tenured region 中对象的存活率很小或者基本没有对象存活,那么 G1 就会在这个阶段将其回收掉,而不用等到后面的clean up 阶段。这也是 Garbage First 名字的由来。同时,在该阶段,G1 会计算每个 region的对象存活率,方便后面的 clean up 阶段使用 。
  • 最终标记( CMS 中的 Remark 阶段)
    在这个阶段 G1 做的事情跟 CMS 一样, 但是采用的算法不同,G1采用一种叫做 SATB(snapshot-at-the-begining) 的算法能够在 Remark 阶段更快的标记可达对象。
  • 筛选回收(Clean up/Copy)阶段
    在G1中,没有 CMS 中对应的 Sweep 阶段。相反 它有一个 Clean up/Copy 阶段,在这个阶段中,G1 会挑选出那些对象存活率低的 region 进行回收,这个阶段也是和 minor gc 一同发生的,如下图所示:

在这里插入图片描述
G1(Garbage-First)是一款面向服务端应用的垃圾收集器。HotSpot 开发团队赋予它的使命是未来可以替换掉JDK 1.5中发布的 CMS 收集器。 如果你的应用追求低停顿,G1 可以作为选择;如果你的应用追求吞吐量,G1并不带来特别明显的好处。

总结:一个对象的一生

一个对象的一生:我是一个普通的 Java 对象,我出生在 Eden 区,在 Eden 区我还看到和我长的很像的小兄弟,我们在 Eden 区中玩了挺长时间。有一天 Eden 区中的人实在是太多了,我就被迫去了 Survivor 区的 “From” 区(S0 区),自从去了 Survivor 区,我就开始漂了,有时候在 Survivor 的 “From” 区,有时候在 Survivor 的 “To” 区(S1 区),居无定所。直到我 18 岁的时候,爸爸说我成人了,该去社会上闯闯了。于是我就去了年老代那边,年老代里,人很多,并且年龄都挺大的,我在这里也认识了很多人。在老年代里,我生活了很多年(每次GC加一岁)然后被回收了。

在这里插入图片描述

相关文章:

【JVM】垃圾回收(GC)详解

垃圾回收(GC)详解 一. 死亡对象的判断算法1. 引用计数算法2. 可达性分析算法 二. 垃圾回收算法1. 标记-清除算法2. 复制算法3. 标记-整理算法4. 分代算法 三. STW1. 为什么要 STW2. 什么情况下 STW 四. 垃圾收集器1. CMS收集器(老年代收集器&…...

阿里云服务器公网带宽多少钱1M?

阿里云服务器公网带宽计费模式按固定带宽”计费多少钱1M?地域不同带宽价格不同,北京、杭州、深圳等大陆地域价格是23元/Mbps每月,中国香港1M带宽价格是30元一个月,美国硅谷是30元一个月,日本东京1M带宽是25元一个月&am…...

应用DeepSORT实现目标跟踪

在ByteTrack被提出之前,可以说DeepSORT是最好的目标跟踪算法之一。本文,我们就来应用这个算法实现目标跟踪。 DeepSORT的官方网址是https://github.com/nwojke/deep_sort。但在这里,我们不使用官方的代码,而使用第三方代码&#…...

Beyond Compare 4 30天评估到期 解决方法

Beyond Compare 4 用习惯了,突然提示评估到期了,糟心😄 该方法将通过修改注册表,使BeyondCompare 版本4可以恢复到未评估状态,使其可以持续使用30天评估😄。 修改注册表 第一步:打开注册表。 在…...

化妆品用乙基己基甘油全球市场总体规模2023-2029

乙基己基甘油又名辛氧基甘油,分子式 C11H24O3,分子量 204.306,沸点 325℃,密度 0.962,无色液体,涂抹性能适中的润肤剂、保湿剂及润湿剂。它能够在提高配方滋润效果的同时又具有柔滑的肤感。加入在某些膏霜体…...

springboot家政服务管理平台springboot29

大家好✌!我是CZ淡陌。一名专注以理论为基础实战为主的技术博主,将再这里为大家分享优质的实战项目,本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目,希望你能有所收获,少走一些弯路…...

【网络安全】如何保护IP地址?

使用防火墙是保护IP地址的一个重要手段。防火墙可以监控和过滤网络流量,并阻止未经授权的访问。一家网络安全公司的研究显示,超过80%的企业已经部署了防火墙来保护他们的网络和IP地址。 除了防火墙,定期更新操作系统和应用程序也是保护IP地址…...

2023年失业了,想学一门技术可以学什么?

有一个朋友,大厂毕业了,原本月薪估计有5w吧,年终奖也不错,所以早早的就买了房生了娃,一直是人生赢家的姿态。 但是今年突然就被毕业了,比起房货还有个几百万没还来说,他最想不通的是自己的价值…...

MySQL-MVCC(Multi-Version Concurrency Control)

MySQL-MVCC(Multi-Version Concurrency Control) MVCC(多版本并发控制):为了解决数据库并发读写和数据一致性的问题,是一种思想,可以有多种实现方式。 核心思想:写入时创建行的新版…...

ArcGIS中的镶嵌数据集与接缝线

此处介绍一种简单方法,根据生成的轮廓线来做镶嵌数据集的拼接。 一、注意修改相邻影像的上下重叠。注意修改ZOrder和每幅影像的范围。 二、修改新的镶嵌线并且导出影像文件。 三、还有其他方法和注意事项。...

网络安全工程师自主学习计划表(具体到阶段目标,保姆级安排,就怕你学不会!)

前言 接下来我将给大家分享一份网络安全工程师自学计划指南,全文将从学习路线、学习规划、学习方法三个方向来讲述零基础小白如何通过自学进阶网络安全工程师,全文篇幅有点长,同学们可以先点个收藏,以免日后错过了。 目录 前言…...

Linux 根据 PID 查看进程名称

ps aux | grep PID...

Python二级 每周练习题21

练习一: 提示用户输入两个正整数,编程求出介于这两个数之间的所有质数并打印输出。 显示格式为“*数是质数。” 答案: x(int(input(请输入第一个正整数:)),int(input(请输入第二个正整数:))) #变量x存放input输入的两个整数的元组 Num1min(x) #判断输入数字…...

【算法训练-数组 三】【数组矩阵】螺旋矩阵、旋转图像、搜索二维矩阵

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是螺旋矩阵,使用【二维数组】这个基本的数据结构来实现 螺旋矩阵【EASY】 二维数组的结构特性入手 题干 解题思路 根据题目示例 mat…...

LED灯实验--汇编

asm-led.S .text .global _start _start: /* 1. led灯的初始化 *//* 1.1 使能GPIOE、DPIOF外设控制器的时钟 */ldr r0, 0x50000A28ldr r1, [r0]orr r1, r1, #(0x3 << 4)str r1, [r0]/* 1.2 设置PE10、PE8、PF10引脚为输出模式 */ldr r0, 0x50006000ldr r1, [r0]bic r1,…...

Android多线程学习:线程池(一)

一、概念 线程池&#xff1a;创建并维护一定数量的空闲线程&#xff0c;当有需要执行的任务&#xff0c;就交付给线程池中的一个线程&#xff0c;任务执行结束后&#xff0c;该线程也不会死亡&#xff0c;而是回到线程池中重新变为空闲状态。 线程池优点&#xff1a; 1、重用…...

网络安全(黑客技术)—小白自学笔记

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成熟入…...

掌握核心技巧就能创建完美的目录!如何在Word中自动创建目录

目录是Word布局的一个重要因素&#xff0c;尤其是在编写较长的文档时。那么&#xff0c;你如何在你的作品中添加目录呢&#xff1f;在这篇文章中&#xff0c;我将分享一些基于Word2016自动创建目录的经验。希望它能或多或少地帮到你。 自动创建目录 1、输入目录文本的名称&am…...

正则表达式中re.match、re.search、re.findall的用法和区别

这位作者的例子写的非常好&#xff0c;记录一下&#xff0c;目前用到的比较多的是findall 正则表达式中re.match、re.search、re.findall的用法和区别_<re.match object; span(0, 270), match<a href"/-CSDN博客...

算法题:买卖股票的最佳时机含手续费(动态规划解法贪心解法-详解)

这道题有两种解法&#xff1a;动态规划 or 贪心算法。 贪心算法的提交结果要比动态规划好一些&#xff0c;总体上动态规划的解法更容易想到。&#xff08;完整题目附在了最后&#xff09; 1、动态规划解法 设置两个数&#xff0c;dp[0]表示遍历到股票prices[i]时手里没有股…...

【gcc】RtpTransportControllerSend学习笔记 4:码率分配

本文是woder大神 的文章的学习笔记。 大神的webrtc源码分析(8)-拥塞控制(上)-码率预估 详尽而具体,堪称神作。 gcc保障带宽公平性,预估码率后要分配码率,实现qos效果: webrtc源码分析(9)-拥塞控制(下)-码率分配 是 woder 大神进一步给出的另一篇神作。 本文是对(https://w…...

「专题速递」AR协作、智能NPC、数字人的应用与未来

元宇宙是一个融合了虚拟现实、增强现实、人工智能和云计算等技术的综合概念。它旨在创造一个高度沉浸式的虚拟环境&#xff0c;允许用户在其中交互、创造和共享内容。在元宇宙中&#xff0c;人们可以建立虚拟身份、参与虚拟社交&#xff0c;并享受无限的虚拟体验。 作为互联网大…...

什么是基于意图的网络(IBN)

基于意图的网络是一种网络技术&#xff0c;它根据业务意图&#xff08;来自网络管理员的服务请求&#xff09;配置 IT 基础架构&#xff0c;无需任何人工干预&#xff0c;它不断提供关键的网络见解&#xff0c;并不断调整硬件配置以确保满足意图&#xff0c;它将网络从以设备为…...

知识增强语言模型提示 零样本知识图谱问答10.8

知识增强语言模型提示 零样本知识图谱问答 摘要介绍相关工作方法零样本QA的LM提示知识增强的LM提示与知识问题相关的知识检索 摘要 大型语言模型&#xff08;LLM&#xff09;能够执行 零样本closed-book问答任务 &#xff0c;依靠其在预训练期间存储在参数中的内部知识。然而&…...

虚拟现实项目笔记:SDK、Assimp、DirectX Sample Browser、X86和X64

文章目录 SDK是什么Assimp是什么DirectX Sample Browser是什么X86和X64生成解决方案和重新生成解决方案 SDK是什么 SDK是Software Development Kit的英文缩写&#xff0c;意思是软件开发包。 软件开发包中往往包含有多种辅助进行软件开发的内容&#xff0c;包括一些软件开发工…...

openwrt rm500u ncm方式拨号步骤记录

1.进入设备页面 用户名&#xff1a;root 2.创建接口 3.配置接口 国内APN 信息 中国移动APN&#xff1a;CMNET 中国联通APN&#xff1a;3GNET 中国电信APN&#xff1a;CTNET 4.防火墙配置 5.点击Save&Apply 6.配置完成后重启设备。重新进入设备页面&#xff0c;可以看…...

使用js代码将一个值为“1=增量,2=全量“的字符串转化为一个数组,数据格式为[{value:““,label:“‘‘}]

const str "1增量&#xff0c;2全量"; const arr str.split(",").map(item > {const [value, label] item.split("");return { value, label}; });...

图片调色盘

图片预览 配置安装 Color-Thief 安装包使用文档 yarn add colorthief -S // npm install colorthief --save代码 <template><div class"img-thief"><div class"container"><div class"thief-item" v-for"(item, in…...

一文读懂Base64

这几天在和第三方交互的时候&#xff0c;对方返回的数据是base64格式的数据&#xff0c;所以这两天又彻底捋了下Base64的来龙去脉。之前看过一篇文章说的非常好&#xff08;再找到给加上链接&#xff09;&#xff0c;我在这不详细说明了&#xff0c;只说转换过程。 还是使用中…...

CCF CSP认证 历年题目自练 Day20

题目一 试题编号&#xff1a; 201903-1 试题名称&#xff1a; 小中大 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 512.0MB 问题描述&#xff1a; 题目分析&#xff08;个人理解&#xff09; 常规题目&#xff0c;先看输入&#xff0c;第一行输入n表示有多少数字&am…...

国企网站建设合同/查关键词排名软件

本篇主要讲解MySQL中的外键约束。 一约束概述 创建约束的目的就是保证数据的完整性和一致性。约束根据约束针对的字段的数目的多少划分为表级约束和列级 约束。 如果约束按照功能来划分的话刻印划分为&#xff1a;NOT NULL(非空约束)、PRIMARY KEY(主键约束)、UNIQUE KEY(唯…...

南京专业做网站公司/搜索引擎排名竞价

[南洋理工大学]2021年THE世界大学综合排名第47名[南洋理工大学]2020年THE世界大学综合排名第48名[南洋理工大学]2019年THE世界大学综合排名第51名[南洋理工大学]2018年THE世界大学综合排名第52名[南洋理工大学]2019年THE世界大学专业排名商业与经济专业第65名[南洋理工大学]201…...

公司做网站/人员优化方案

在 Unity 中,可以使用 Shader 来实现颜色渐变的效果。 要实现这个效果,你需要在 Unity 中创建一个新的 Shader 文件。你可以使用 Surface Shader 来简化这个过程,因为 Surface Shader 会自动为你生成颜色缓冲区和基本光照。 在 Shader 中,你需要定义一些变量来存储颜色渐变…...

最新章节 第一百四十七章 做视频网站/可靠的网站优化

添加verifyed标签 http://blog.csdn.net/terence427/article/details/16840697转载于:https://www.cnblogs.com/itzxy/p/6255833.html...

教做flash的网站/国内新闻最新消息今天简短

直接上代码吧 尝试将项目复制后建一个新的项目&#xff0c;结果总是有问题&#xff0c;不过可以把原项目转换为新项目&#xff0c;方法如下&#xff1a; 1.项目右键在android tools 有个 rename application package选项&#xff0c;这是改包名的&#xff0c;改完这个就是两个不…...

wordpress收藏中心代码/百度推广的定义

请你计算按照手机键盘&#xff08;999 键输入法&#xff09;输入字母的方式&#xff0c;键入给定字符串&#xff08;由小写字母构成&#xff09;所花费的时间。 具体键入规则和花费时间如下描述&#xff1a; 对于同一键上的字符&#xff0c;例如 a,b,ca,b,ca,b,c 都在 “1” 键…...