Java GC机制 —— 个人笔记

news2024/11/25 21:34:34

文章目录

    • JVM内存区
    • 对象是否需要回收?
      • 1. 引用计数法
      • 2. 可达性分析法(根搜索算法)
        • Java的引用
    • 对象何时被回收?
    • 回收策略
      • 回收策略1:引用计数算法
      • 回收策略2:标记清除算法(Mark-Sweep)
      • 回收策略3:标记整理算法(Mark-Mark-Compact)
      • 回收策略4:复制算法(Copying)
      • 回收策略5:分待回收机制
        • 内存区分配
        • 为何还要对新生代进行划分?
        • 为啥Survivor区需要两个?
    • 垃圾收集器
      • 新生代:Serial
      • 新生代:ParNew
      • 新生代:Parallel Scavenge
      • 老年代:Serial Old
      • 老年代:Parallel Old
      • CMS收集器
      • 混合:G1
    • 复习

文章源于学习若干个博客过程中整合,图源于图文并茂,万字详解,带你掌握 JVM 垃圾回收!

7种垃圾回收器特点,优劣及使用场景

GC garbage collection 垃圾回收

C/C++中,对象的申请和释放都需要程序员自己进行操作,然而程序员如果忘记对内存空间进行正确的释放,可能导致内存泄漏。

为避免此类情况发生,GC机制可以让程序员开发过程中更专注程序应用本身,而无需考虑内存泄露问题。

  • GC自动检测对象是否超过作用域,自动回收内存
  • 垃圾收集器自动管理

JVM内存区

JVM一共有五个区域: Method Area, VM stack, Native Mathod Stack, Heap, Program Counter Register

其中GC回收的区域为:

  1. 堆区
  2. 方法区

GC回收区域的共同点为:线程共享

对象是否需要回收?

对象无引用,或不可达

判断方法

1. 引用计数法

static class Test{
    public Test instance;
}

public void run() {
    Test t1 = new Test();
    Test t2 = new Test();
    t1.instance = t2; 
    t2.instance = t1;
    // t1和t2相互引用
}

如果我们执行run()方法后,虽然t1和t2不会再被访问,但由于t1, t2相互引用对方,引用计数器不为0,无法对他们进行回收。所以,市面上主流的Java虚拟机都没有使用这个算法,而是使用可达性分析法

2. 可达性分析法(根搜索算法)

通过 GC Roots根对象来作为起始节点,从这些节点开始,根据引用关系向下搜索,搜索过程的就是一条引用链(Reference Chain)。不在这个链里面的对象,就认为是 可回收的

在这里插入图片描述
哪些对象可以作为GC Roots?

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象,参数,局部变量,临时变量
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈JNI引用对象

虚拟机栈引用的对象

当运行某个函数的时候,JVM就会为这个函数在栈区开辟内存,如果运行main函数,那么JVM为main函数的局部变量在栈区开辟内存

public class Test {
    public static void main(String[] args) {
		Test a = new Test();//a是栈中局部变量
		a = null; //a为null的时候,他和原本的new Test()断开连接
		//对象回收
    }
}

方法区中类静态属性引用的对象

方法区本身用于存放类的信息:名称,父类,接口,变量等

public class Test {
    public static Test s; //s为类静态属性引用的对象
    public static void main(String[] args) {
		Test a = new Test();
		a.s = new Test();
		a = null;
    }
}

a = null 时,由于 a 原来指向的对象与 GC Root (变量 a) 断开了连接,所以 a 原来指向的对象会被回收。
然而s是类静态属性,且被赋值引用,被认为是GC Root,s依然 可达

方法区中常量引用的对象


public class Test {
	public static final Test s = new Test();
    public static void main(String[] args) {
	    Test a = new Test();
	    a = null;
    }

同上,a对象被回收不会影响到常量s指向的对象

本地方法栈中 JNI(Java Native Interface引用) 的对象

  • 一个 java 调用非 java 代码的接口
  • 可能由 C 或 Python等其他语言实现的
  • 通过 JNI 来调用本地方法, 而本地方法是以库文件的形式存放的(Windows为dll, unix上为so文件)

区别?

Java方法本地方法
虚拟机会创建一个栈桢并压入 Java 栈虚拟机会保持 Java 栈不变,不会在 Java 栈祯中压入新的祯,虚拟机只是简单地动态连接并直接调用指定的本地方法。
Java的引用

强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)

//强引用
String s = new String("hello");
System.gc();
System.out.println(s);

和前文一样,强引用存在,垃圾收集器永远不会回收被引用的对象,只有当引用被设为null的时候,对象才会被回收。如果赋值给static变量,对象很长一段时间都不会被回收

//软引用
String s = new String("hello");
//强引用添加到软引用
SoftReference<String> softReference = new SoftReference<>(s);
s=null;
//执行垃圾回收
System.gc();
//再次获取
if(softReference !=null ){
    System.out.println(softReference.get());
}

GC过程中,如果内存充足,软引用对象不会被释放

//弱引用
WeakReference<String> weakReference = new WeakReference<>(new String("hello"));
 //执行垃圾回收
 System.out.println("执行垃圾回收之前");
 System.out.println(weakReference.get());
 System.gc();
 System.out.println("执行垃圾回收之后:");
 System.out.println(weakReference.get());

只要系统执行完垃圾回收,无论内存是否足够,弱引用变量指向的对象都会被回收

ReferenceQueue<String> referenceQueue = new ReferenceQueue<>();
PhantomReference<String> phantomReference = new PhantomReference<>(new String("hello"), referenceQueue);
System.gc();
System.out.println(referenceQueue.remove().get());

无论内存是否足够,弱引用变量指向的对象都会被回收,和虚引用的区别在于,无法通过虚引用来取得一个对象实例,虚引用也不会对生成他的对象生存时间产生影响。

作用:对象被收集器回收的时候得到系统通知

对象何时被回收?

  • 自动调用的情况:

    • 程序创建新对象/基本类型数据
    • 内存空间不足
  • 手动调用的情况

    • System.gc()

回收策略

回收策略1:引用计数算法

  • 发现垃圾时,立即回收。

  • 最大限度减少程序暂停,因为发现后立即回收,减少了程序因内存爆满而被迫停止的现象

  • 时间开销大,因为引用计数算法需要时刻监控引用计数器的变化。

  • 无法回收循环引用的对象

回收策略2:标记清除算法(Mark-Sweep)

未引用对象并不会被立即回收,垃圾对象将一直累计到内存耗尽为止,当内存耗尽时,程序将会被挂起,垃圾回收开始执行

  1. 遍历所有对象,标记所有的可达对象
  2. 会遍历所有对象,清除没有标记的对象

优点:简单,快速
缺点:标记和清除过程效率不高 —— 之后会产生大量不连续的内存碎片,提高触发另一次垃圾收集动作的概率
在这里插入图片描述

回收策略3:标记整理算法(Mark-Mark-Compact)

  1. 标记过程仍然与“标记-清除”算法一样

  2. 第二阶段不对可回收对象进行清理,而让所有存活的对象都向一端移动

在这里插入图片描述

回收策略4:复制算法(Copying)

改进了标记-清除算法的效率

内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
在这里插入图片描述
优点

  1. 不用考虑内存碎片
  2. 简单高效

缺点

  1. 内存缩小一半

回收策略5:分待回收机制

于是我们结合前面的2,3,4 三种策略,得到了当前最流行的分带回收机制算法

  • 新生代:复制算法
  • 老年代:标记-清除算法、标记-整理算法
弱分代假说:绝大多数对象都是朝生夕死的。
强分代假说:熬过越多次的垃圾回收的对象,就越难消亡

绝大多数对象在前几次GC过程中回收,经过多次GC过程未被回收的对象很难消亡。

于是把对象分为 新生代老年代。然后分配到不同的区域后,执行不同的策略。比例一般为1:2

新生代老年代
大部分对象会被回收难被回收
频繁使用可达性分析法较少频率回收
存活对象被复制到幸存者区域后被释放

详细说明

新生代

  1. 所有new的对象先出现在新生代中
  2. 新生代内存满了触发一次GC事件(Minor garbage collection)
  3. 无法回收的对象移动到老年代
  4. Minor garbage collection为全局暂停事件,垃圾回收过程结束其他线程才可运行

老年代

  1. 老年代被占满时也会触发GC时间(Major garbage collection)
  2. 也需要全局暂停
  3. 涉及所有存活对象,更慢。受老年代垃圾回收器影响

除此之外,还有一个永久代(在非heap内存)

  1. 存储了描述应用程序类和方法的源数据
  2. JVM 在运行时基于应用程序所使用的类产生
  3. 类不在被其他类所需要,同时其他类需要更多的空间的时候才会被回收(此回收过程为Full garbage collection)
    在这里插入图片描述
内存区分配

前面说过,新生代(Young generation)、老年代(Old generation)所占空间比例为 1 : 2,其中新生代还会被分为三个空间

  • 1个伊甸园空间(Eden)
  • 2个幸存者空间(Fron Survivor、To Survivor)

默认情况下,新生代空间的分配:Eden : Fron : To = 8 : 1 : 1
在这里插入图片描述

为何还要对新生代进行划分?

假设我们没有survivor

  1. Eden区每进行一次Minor GC,存活的对象就会被送到老年代。
  2. 老年代很快被填满,触发Major GC(因为Major GC一般伴随着Minor GC,也可以看做触发了Full GC)
  3. 老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC长得多

如果不划分新生代区,有无其他方法避免上述情况?

方案优点缺点
增加老年代空间更多存活对象才能填满老年代。降低Full GC频率随着老年代空间加大,一旦发生Full GC,执行所需要的时间更长
减少老年代空间Full GC所需时间减少老年代很快被存活对象填满,Full GC频率增加

上述两种解决方案都不能从根本上解决问题

Survivor:就是减少被送到老年代的对象,进而减少Full GC的发生。Survivor的预筛选保证:经历16次Minor GC还能存活的对象,才会被送到老年代。

为啥Survivor区需要两个?

若只有一个Survivor区,会出现以下情况

  1. Eden满了,触发一次Minor GC,Eden中的存活对象就会被移动到Survivor区,此时Eden和Survivor各有一些存活对象
  2. Minor GC到底一定次数后,Survivor区会把部分数据存到Old区,eden也会把数据存放到Survivor区
  3. 但是Eden存到Survivor的数据不一定能刚好存入Survivor空缺部分的数据,导致内存碎片化

在这里插入图片描述
应该建立两块Survivor区

  1. 刚刚新建的对象在Eden中
  2. 经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor space S0,Eden被清空;
  3. 等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制到survivor space S1

在这里插入图片描述

垃圾收集器

在这里插入图片描述
新生代收集器

  • Serial
  • ParNew
  • parallel
    老年代收集器
  • Serial Old
  • CMS
  • Parallel Old
    新生代和老年代收集器
    G1

常用组合
在这里插入图片描述

新生代:Serial

  • 单线程收集器
  • 使用**“复制”**算法
  • GC过程中,所有线程必须暂停
    在这里插入图片描述
    特点
  1. 简单,无上下文切换,效率高
  2. 用户体验较差,其不知情情况下停止所有线程
  3. 适用场景:Client 模式(桌面应用);单核服务器。
  4. 使用命令如下开启Serial作为新生代收集器
-XX:+UserSerialGC #选择Serial作为新生代垃圾收集器

新生代:ParNew

serial的一个多线程版本
多核机器上,其默认开启的收集线程数与cpu数量相等。可以通过如下命令进行修改

-XX:ParallelGCThreads #设置JVM垃圾收集的线程数  

在这里插入图片描述

当用户线程都执行到安全点时,所有线程暂停执行,采用复制算法进行垃圾收集工作

特点

  • 有效利用CPU
  • 用户体验较差,其不知情情况下停止所有线程
  • Server模式常用,因为CMS收集器只能和serial或者parNew联合使用。可以使用如下命令进行强制指定
-XX:UseParNewGC #新生代采用ParNew收集器  

新生代:Parallel Scavenge

  • 复制算法
  • 对比parNew,PS收集器关注缩短GC停顿时间,从而达到可控的吞吐量

吞吐量 = 运行用户代码时间 运行用户代码时间 + 垃圾收集时间 吞吐量=\frac{运行用户代码时间}{运行用户代码时间+垃圾收集时间} 吞吐量=运行用户代码时间+垃圾收集时间运行用户代码时间

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

垃圾收集器每 100 秒收集一次,每次停顿 10 秒,和垃圾收集器每 50 秒收集一次,每次停顿时间 7 秒,虽然后者每次停顿时间变短了,但是总体吞吐量变低了,CPU 总体利用率变低了。
在这里插入图片描述

特点

  • 高吞吐量,高CPU利用率,可控
  • 使用高吞吐量高CPU利用率场景,如高速运算,少量交互的情况

老年代:Serial Old

Serial Old是Serial收集器的老年代版本
标记-整理算法

适用场景

  • Client模式;
  • 单核服务器;
  • 与Parallel Scavenge收集器搭配;
  • 作为CMS收集器的后备方案,在并发收集发生Concurrent Mode Failure时使用

老年代:Parallel Old

Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法

在这里插入图片描述
一般搭配Parallel Scavenge 收集器

参数指定

-XX:+UserParallelOldGC

CMS收集器

获取最短回收停顿时间为目标的收集器。采用的算法是“标记-清除

  1. 标记GC Roots 能够直接关联到达对象
  2. 并发标记,进行GC Roots Tracing 的过程
  3. 重新标记,修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录
  4. 标记清除算法清除对象
    在这里插入图片描述
    特点
  • 并发收集,低停顿
  • CPU资源非常敏感,默认回收线程数(CPU数量+3)/4,CPU数量不足4个对用户影响较大
  • 无法处理浮动垃圾
    • 可能会出现“Concurrent Mode Failure”失败而导致一次FullGC的产生
    • 此时用SerialOld来重新进行老年代GC
    • CMS并发清理阶段用户线程还在运行,伴随程序运行自然还会有新的垃圾产生,所以只能等待下一次GC清楚,无法填满后GC
    • -XX:CMSInitiatingOccupancyFraction修改CMS触发的百分比
  • 空间碎片

混合:G1

面向服务端应用的垃圾收集器,目前是JDK9的默认垃圾收集器

  • 并行并发
  • 分代收集。能够采用不同的方式去处理新创建的对象和已经存活了一段时间的对象
  • 整体上来看基于“标记-整理”,部上看是基于复制算法,不产生空间碎片
  • 可预测的停顿

Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但两者之间不是物理隔离的。他们都是一部分Region的集合

在这里插入图片描述
一个方块对应一个区域,他的身份不定,每种身份的数量也不一定

JVM启动设置每个区为2的次幂大小,最多为2048个区域( 2048 × 32 M = 64 G 2048\times 32M=64G 2048×32M=64G)假如设置 -Xmx8g -Xms8g,则每个区域大小为 8g/2048=4M。

作用

  • 避免在整个Java堆全区域GC
    • 跟踪各个区的价值大小(回收空间大小,所需时间)得到优先队列
    • 每个区域都有Remembered Set 来实时记录 引用类型数据和其他区域数据的关系

在这里插入图片描述

  1. 初始阶段:标记处GC直接关联对象(需要停止线程,单线程执行)
  2. 并发阶段:GC roots开始对heap对象进行可达分析,和用户线程并行
  3. 最终标记:修正并行过程中变动的记录
  4. 筛选回收:对各个 Region 的回收价值和成本进行排序,根据用户所期望的 GC 停顿时间来指定回收计划 —— 最少的时间回收垃圾最多的区域,这里需要停止用户线程

复习

  1. JVM的五大内存区是?
  2. 判定是否需要回收某个对象的方法有哪些?优缺点是什么?
  3. 为什么市面上多采用可达性分析方法
  4. 可达性分析方法如何判断GC Root
  5. 四种引用的区别是什么
  6. 对象什么时候会被回收?主动回收和被动回收的区别?
  7. 回收策略有哪些?
  8. 标记清除算法和标记整理算法的区别?
  9. 分带回收机制和Copying机制主要区别在哪?
  10. 这些回收策略的优缺点是什么?
  11. 新生代,老年代如何划分?
  12. 新生代如何变成老年代?
  13. Minor, Major, Full GC的区别
  14. 为何Survivor区设置为两个?少一个会如何?
  15. 为啥主流的回收策略是分带回收机制?
  16. 常见的垃圾收集器有哪些?一般他们如何搭配使用?

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

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

相关文章

MySQL 8.0 Clone Plugin 详解

文章目录 前言1. 克隆插件安装2. 克隆插件的使用2.1 本地克隆2.2 远程克隆 3. 克隆任务监控4. 克隆插件实现4.1 Init 阶段4.2 File Copy4.3 Page Copy4.4 Redo Copy4.5 Done 5. 克隆插件的限制6. 克隆插件与 Xtrabackup 的异同7. 克隆插件相关参数后记 前言 克隆插件&#xff…

武汉某母婴用品公司 - 集简云连接ERP和营销系统,实现库存管理的自动化

品牌介绍与关怀理念 武汉某母婴用品公司是一家专注于高端孕婴童护理用品的企业&#xff0c;积极响应和关怀孕产人群&#xff0c;全方位提供从待产用品到产后护理用品&#xff0c;再到婴童洗护用品和初生婴儿用品等一系列全面的母婴产品。我们的使命是满足客户的需求&#xff0…

光学仿真 | 仿真推动以人类视觉感知为本的汽车显示设计

如果产品设计无法使终端用户产生共鸣&#xff0c;就不会存在卓越的工程设计。您可以设计一种结构坚固的方向盘&#xff0c;但如果它被放在错误的位置&#xff0c;就无法实现其用于转向的主要目的。 同样&#xff0c;在围绕人类视觉进行设计时&#xff0c;显示器其实无需具备尽…

分布式任务调度(01)--分布式锁

Quartz集群模式可水平扩展&#xff0c;也可分布式调度&#xff0c;但需业务方在数据库中添加对应表&#xff0c;有强侵入性。于是探索分布式锁模式。 1 超时关单 通常做定时任务每2min检查前半小时的订单&#xff0c;将待支付订单列表查出&#xff0c;然后对订单中的商品进行…

数据结构(c语言版) 队列

链队列 要求&#xff1a;实现链队列的创建、初始化、入队、出队 &#xff08;先进先出&#xff09; 代码 // // Created by My.cy on 2023/10/19. // //链队列 创建、初始化、入队、出队 先进先出#include <stdio.h> #include <malloc.h>//定义结构体 struct…

【电源专题】PSE如何与PD握手协商功率等级?

在文章:【电源专题】POE连接方式与功率等级划分 中我们讲到POE协议对不同的PD设备进行划分,比如根据不同的供电标准又可以细分成好几种不同的类型(Type1~Type4)和功率等级。 那么有这么多功率等级,PSE怎么知道PD是哪种类型呢?怎么能进行握手协商呢? 下图为PSE与PD设备在…

Linux学习第36天:Linux RTC 驱动实验:时间是一条流淌的河

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 RTC就是实时时钟。 本笔记主要学习Linux RTC驱动试验&#xff0c;主要内容包括Linux内核RTC驱动简介、I.MX6U内部RTC分析、RTC时间查看与设置。因为Linux内核已经…

用 bitsandbytes、4 比特量化和 QLoRA 打造亲民的 LLM

众所周知&#xff0c;LLM 规模庞大&#xff0c;如果在也能消费类硬件中运行或训练它们将是其亲民化的巨大进步。我们之前撰写的 LLM.int8 博文 展示了我们是如何将 LLM.int8 论文 中的技术通过 bitsandbytes 库集成到 transformers 中的。在此基础上&#xff0c;我们不断努力以…

怎么学编程效率高,编程练习网站编程软件下载,中文编程开发语言工具下载

怎么学编程效率高&#xff0c;编程练习网站编程软件下载&#xff0c;中文编程开发语言工具下载 给大家分享一款中文编程工具&#xff0c;零基础轻松学编程&#xff0c;不需英语基础&#xff0c;编程工具可下载。 这款工具不但可以连接部分硬件&#xff0c;而且可以开发大型的…

word方框中的对勾如何打?

问题描述&#xff1a;平时在填一些电子版表格时&#xff0c;需要在方框里打对勾&#xff0c;这时如何打呢&#xff1f; 问题解决&#xff1a;符号→其他符号→字体调整为Wingdings 2→找到方框里有对勾的符号&#xff0c;插入即可。 具体如下图所示&#xff1a;

武汉凯迪正大—气体密度继电器校验仪

产品概述 武汉凯迪正大SF6气体密度继电器是用来监测运行中SF6开关本体中SF6气体密度变化的重要元件&#xff0c;其性能的好坏直接影响到SF6开关的运行安全。现场运行的SF6气体密度继电器因不常动作&#xff0c;经过一段时期后常出现动作不灵活、触点接触不良等现象&#xff0c…

Flink架构

1、Apache Flink集群的核心架构&#xff1a; 1、client&#xff08;作业客户端&#xff09;&#xff1a;提交任务的地方叫做客户端 2、JobManager&#xff08;作业管理器&#xff09;&#xff1a;作用是用于管理集群中任务 3、TaskManager&#xff08;任务管理器&#xff09;&a…

wsl2 ubuntu22.04安装docker

1. 安装 docker 官网的步骤一步一步安装即可 Install Docker Engine on Ubuntu | Docker Docs 2. 安装完毕之后&#xff0c;不出意外的话当你运行docker version或者其他命令的时候你会报如下错误&#xff1a; Cannot connect to the Docker daemon at unix:///var/run/docke…

蓝桥杯:分数

题目 思路 等比数列求和&#xff0c;手算然后输出 代码&#xff08;已过&#xff09; #include <iostream> using namespace std; int main() {// 请在此输入您的代码int a1024*1024-1;int b1024*512;cout<<a<<"/"<<b;return 0; }

Unity 实现文字过长显示省略号

为了整体效果&#xff0c;当文字过长时&#xff0c;我们就会把超出范围的文字弄成省略号。 要实现文字过长显示省略号&#xff0c;只需要使用TextMeshPro&#xff0c;并设置Overflow属性为Ellipsis即可。 如下图&#xff1a; 记。

【刷题篇】动态规划(三)

文章目录 1、第 N 个泰波那契数2、三步问题3、使用最小花费爬楼梯4、解码方法5、不同路径6、不同路径 II 1、第 N 个泰波那契数 泰波那契序列 Tn 定义如下&#xff1a; T0 0, T1 1, T2 1, 且在 n > 0 的条件下 Tn3 Tn Tn1 Tn2 给你整数 n&#xff0c;请返回第 n 个泰波…

Spring基础(2):放弃XML,走向注解

上一篇并没有实际地带大家去看源码&#xff0c;而是介绍了两个概念&#xff1a; BeanDefinitionBeanPostProcessor 当然&#xff0c;我介绍得非常笼统&#xff0c;不论是BeanDefinition还是BeanPostProcessor其实都有着较为复杂的继承体系&#xff0c;种类也很多。作为Spring…

文心一言 VS 讯飞星火 VS chatgpt (130)-- 算法导论11.2 2题

二、用go语言&#xff0c;对于一个用链接法解决冲突的散列表&#xff0c;说明将关键字 5,28,19,15,20,33,12,17,10 插入到该表中的过程。设该表中有 9 个槽位&#xff0c;并设其散列函数为 h(k)k mod 9。 文心一言&#xff1a; 在这个问题中&#xff0c;我们使用 Go 语言来解…

Day23力扣打卡

打卡记录 将 x 减到 0 的最小操作数&#xff08;逆向思维 滑动窗口&#xff09; 链接 将 x 减到 0 的最小操作数&#xff0c;可以逆向思考&#xff0c;求一个数组中的最大长度的滑动窗口&#xff0c;来使得这个窗口里的数等于 全数组之和 - x 的值。 class Solution { publ…

MySQL(11):数据处理之增删改

插入数据 方式1&#xff1a; 一条一条的添加数据 为表的所有字段按默认顺序插入数据 INSERT INTO 表名 VALUES (value1,value2,....);# 没有指明添加的字段 INSERT INTO emp1 VALUES (1,TOM,2023-11-06,3400);没有指明添加的字段&#xff0c;要按照声明顺序&#xff0c;进行…