JAVA进阶之路JVM-3:JVM内存模型,运行时数据区域划分,程序计数器,虚拟机栈,本地方法栈,堆,元空间,字符串常量池

JVM内存模型

对于 Java 程序员来说,在虚拟机自动内存管理机制下,不再需要像 C/C++ 程序开发程序员这样为每一个操作去写对应的 delete / free 操作,不容易出现内存泄漏和内存溢出问题。正是因为 Java 程序把内new存控制权利交给JVM虚拟机。一旦出现内存泄漏和溢出方面的问题,如果不了解虚拟机是怎样使用内存的,那么排查错误将会是一个非常艰巨的任务。

JVM 虚拟机在执行 java 程序的过程中,会把它管理的内存划分成若干个不同的区域,每个区域有各自的不同的用途、创建方式及管理方式。有些区域随着虚拟机的启动一直存在,有些区域则随着用户线程的启动和结束而建立和销毁,这些共同组成了 Java 虚拟机的运行时数据区域,也被称为 JVM 内存模型

运行时数据区域划分

JVM虚拟机在执行JAVA程序的过程中会把它管理的内存划分成若干个不同的数据区域,由方法区,堆区,虚拟机栈,本地方法栈,程序计数器五部分组成

在这里插入图片描述

版本的差异

  1. JDK 1.8之前分为:线程共享(Heap堆区、Method Area 方法区)、线程私有(虚拟机栈、本地方法栈、程序计数器)
  2. JDK 1.8之后分为:线程共享(Heap堆区、MetaSpace员工间)、线程私有(虚拟机栈、本地方法栈、程序计数器)

在这里插入图片描述

其中虚拟机栈、本地方法栈、程序计数器是线程私有的区域,所以随着线程消亡而结束。而线程共享的 Heap 堆区、MetaSpace 元空间会随着虚拟机的启动,一直存在。

程序计数器

Program Counter Register‘

程序计数器是一块较小的内存空间,是当前线程所执行的字节码的行号指示器

字节码解释器在解释执行字节码文件工作时,每当需要执行一条字节码指令时,就通过改变程序计数器的值来完成.程序中的分支、循环、跳转、异常处理、线程恢复等功能都需要依赖这个计数器来完成。
程序执行过程中,会不断的切换当前执行线程,切换后,为了能让当前线程恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,并且各线程之间计数器互不影响,独立存储

在这里插入图片描述

程序计数器主要作用

  1. 字节码解释器通过改变程序计数器来一次读取命令,从而实现代码的流程控制,如:顺序执行,选择,循环。异常处理
  2. 在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而当线程被切换回来的时候,能够知道当前现成的运行位置,恢复当前线程的执行

程序计数器是唯一一个不会出现OutOfMemoryError的内存区域,它随着现成的创建而创建,随着线程的结束而死亡

Java虚拟机栈

VM Stack

虚拟机栈是线程执行Java程序时,处理Java方法中内容的区域,虚拟机栈也是线程私有的区域,每个Java方法被调用的时候,都会在虚拟机栈中创建一个栈顶,而每个栈帧又由局部变量,操作数栈,动态链接和方法返回四部分组成,有些虚拟机的栈帧还包括了一些附加的信息

在这里插入图片描述

​ JMM内存区域可以粗略的氛围堆内存(Heqp)和栈内存(Stack)其中栈就是VM Stack虚拟机栈,或者说是虚拟机栈中局部变量表部分

​ 局部变量表主要存放了编译器可知的各种基本数据类型变量值(boolean、byte、char、short、int、float、long、double),对象应用(reference类型,它不同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)

在这里插入图片描述

虚拟机栈运行原理

​ 每一次方法调用都会有一个对应的栈帧被压入VM Stack 虚拟机栈,每一个方法调用结束后,代表该方法的栈帧会从VM Stack虚拟机栈中弹出

​ 虚拟机栈是内存的私有区域,并且栈帧不允许被其他线程访问,不存在线程安全问题,栈帧弹出后内存就会被系统回收,所以也不存在垃圾回收问题

在这里插入图片描述

​ 在活动线程中,只有位于栈顶的栈才是有效的,成为当前活动栈帧,代表正在执行的当前方法

​ 在JVM执行引擎运行时,所有指令都只能对当前活动栈帧进行操作。虚拟机栈通过pop和push的方式,对每个方法对应的活动栈帧进行运算处理,方法正常执行结束,肯定会跳转到另一个栈帧上

在这里插入图片描述

活动栈帧被弹出的方式:

java方法有两种返回方式,不管哪种返回方式都会导致当前活动栈帧被弹出

  • return 语句
  • 抛出异常

虚拟机栈可能产生的错误

java虚拟机栈会出现两种错误:StackOverFlowError和OutOfMemoryError

  1. StackOverFlowError:当线程请求栈的深度超过JVM虚拟机栈的最大深度的时候,就抛出StackOverFlowError错误
  2. OutOfMemoryError:JVM的内存大小可以动态扩展,如果虚拟机的动态扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常

虚拟机栈的大小

虚拟机栈的大小可以通过-Xss参数设置,默认单位是byte,也可以使用k,m,g作为单位(不区分大小写)。例如:-Xss 1m

在不同的操作系统下-Xss的默认值不同

  • Linux:1024K
  • MacOs:1024K
  • Windows:默认值依赖于虚拟机的内存

本地方法栈

Native Method Stack

native关键字修饰的本地方法被执行的时候,在本地方法栈中会创建一个栈帧,用于存放该native本地方法的局部变量表、操作数栈、动态链接、方法出口信息。方法执行完毕后,相应的栈帧也会出栈且释放内存空间。也会出现StackOverFlowErrorOutOfMemoryError两种错误

★★堆(Heap)★★

​ Heap 堆区,用于存放对象实例和数组的内存区域

​ Heap 堆区,是 JVM 所管理的内存中最大的一块区域,被所有线程共享的一块内存区域。堆区中存放对象实例,“几乎”所有的对象实例以及数组都在这里分配内存。


每一个 JVM 进程只存在一个堆区,它在 JVM 启动时被创建, JVM 规范中规定堆区可以是物理上不连续的内存,但必须是逻辑上连续的内存。每一个 JVM 进程只存在一个堆区,它在 JVM 启动时被创建, JVM 规范中规定堆区可以是物理上不连续的内存,但必须是逻辑上连续的内存。

  1. 每一个 JVM 进程只存在一个堆区,它在 JVM 启动时被创建, JVM 规范中规定堆区可以是物理上
    不连续的内存,但必须是逻辑上连续的内存。

  2. JVM 规范中描述,所有的对象实例及数组都应该在运行时分配在堆上。而他们的引用会被保存在
    虚拟机栈中,当方法结束,这些实例不会被立即清除,而是等待 GC 垃圾回收。

  3. 由于堆占用内存大,所以是 GC 垃圾回收的重点区域,因此堆区也被称作 GC堆

    (Garbage Collected Heap)


对象逃逸分析

​ Java 世界中“几乎”所有的对象都在堆中分配,但是,随着 JIT 编译器的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化,所有的对象都分配到堆上也渐渐变得不那么“绝对”了

​ 从 JDK 1.7 开始已经默认开启逃逸分析,如果某些方法中的对象引用没有被返回或者未被外面使用 (也就是未逃逸出去),那么对象可以直接在栈上分配内存

堆的组成:新生代+老年代

​ 从垃圾回收的角度,由于现在收集器基本都采用粉黛垃圾收集算法,所以JVM中的堆区往往进行粉黛划分,例如新生代和老年代目的是为了更好地回收内存,或者更快地分配内存


​ 堆区的组成分为新生代(Young Generation)老年代(Old Generation)。

  • 新生代被分为伊甸区(Eden)和幸存者区(from + to),幸存区又被分为

    Survivor 0(from)和Survivor 1(to)

  • 新生代和老年代的比例为1:2,伊甸区和S0、S1比例为8:1:1,不用区域存放对象的用途和方式不同

    1. 伊甸区(Eden):存放大部分新创建对象
    2. 幸存区(Survivor):存放Minor GC 之后,Eden区和幸存区(Survivor)本身没有被回收的对象
    3. 老年代:存放Minor GC之后且年龄计数器达到15(此信息存在与对象头中)依然存活的对象,Major GC和Full GC之后仍然存活的对象

在这里插入图片描述

对空间大小设置

堆区的内存大小是可以修改的,默认轻快下,初始堆内为物理内存的1/64,最大的物理内存的1/4

  • -Xms:设置初始化堆内存,例如:-Xms64m
  • -Xmx:设置最大堆内存,例如:-Xmx64m
  • -Xmn:设置年轻代内存,例如-Xmx32m

Heap堆区中的新生代、老年代的空间分配比例,可以通过java -XX:+PrintFlagsFinal -version命令查看

在这里插入图片描述

  • uintx InitialSurvivorRatio = 8

    新生代Young(Eden/Survivor)空间的初始比例 = 8:代表Eden占新生代空间的80%

  • uintx NewRatio = 2

    老年代Old/新生代Young的空间比例 = 2:代表老年代Old是新生代Young的2倍

因为新生代是由Eden+s0+s1组成的,所以按照上述默认比例,如果Enen区内存大小是40M,那么两个Survivor区就是5M,整个新生代区就是50M,然后可以算出老年代Old区内存大小是100M,堆区总大小就是150M

创建对象的内存分配★★★★★

创建一个新对象,在堆内的分配内存

大部分情况下,对象会在Eden区生成,当Eden区装填满的时候,会触发Young Garbage Collection,即YGC垃圾回收的时候

依然存活的对象会被移送到Survivor区。Survivor区分为S0和S1两块内存区域。每次YGC的时候,它们将存活的对象复制到未使用的Survivor空间(S0或S1),然后将当前正在使用的空间完全清楚,交换两块空间的使用状态。每次交换时,对象的年龄就会+1

如果YGC要以送的对象大于Survivor区容量的上线,则直接移交给老年代。一个对象也不可能永远呆在新生代,在JVM中一个对象从新生代晋升到老年代的阈值默认值是15,可以在Survivor区交换14次后,晋升至老年代

在这里插入图片描述

堆区的分代垃圾收集思想

出于效率的缘故,JVM 的垃圾收集不会对三个区域(伊甸区、幸存区、老年代)进行收集,大部分时候都是回收新生代, HotSpot 虚拟机将垃圾收集分为部分收集( Partial GC )和整堆收集( FulI GC)

部分收集:

  1. 新生代收集YGC(Minor GC/Young GC):回收新生代区域,频率比较高,因为大部分对的存活寿命比较短,在新生代里被回收性能耗费较小。例如:Serial、ParNew、Parallel Scavenge等垃圾收集器都是新生代收集
  2. 老年代收集Old GC:回收老年代区域,例如:Serial Old、CMS、Parallel Old等垃圾回收器都是老年代收集
  3. 混合收集(Mixed GC):收集整个年轻代区域及部分老年代区域,目前只有G1收集器有

**整机收集FGC(Full GC):**回收整个Java堆区,默认堆空间使用带到80%(可调整)的时候会触发FGC。频率根据访问量的多少决定,可能十天也可能一周左右一次(整机收集的频率越少越好)

GC组合垃圾回收只有YGC和FullGC、OldGC不可以单执行。原因是OldGC是STW机制+标记整理算法,相对耗时,只能在关键时刻使用,因此只有FullGC才能出发OldGC


GC垃圾回收的影响

GC耗时太长、GC次数太多会影响进程的性能、导致进程相应变慢、或者无法响应

  • YGC耗时:耗时在几十或者几百毫秒属于正常情况,用户几乎无感知,对程序影响比较少、耗时太长或者频繁、会导致服务器超时问题
  • YGC次数:太频繁、会降低服务的整机性能、高并发服务时、影响会比较大
  • FGC次数:越少越好。比较正常的情况几小时一次,或者几天一次
  • FGC耗时:耗时很长会导致线程频繁被停止,使应用响应变慢,比较卡顿

产生FGC的原因:

  1. 大对象: 系统一次性加载了过多数据到内存中,导致大对象进入了老年代
  2. 内存泄漏: 频繁创建了大量对象,但是无法被回收 (比如 流对象使用完后未调用 lose 方法释放资源) ,先引发 FGC ,最后导致 OOM 。
  3. 程序频繁生成一些长生命周期的对象,当这些对象的存活年龄超过分代年龄时便会进入老年代,最后引发 FGC
  4. 程序 BUG 导致动态生成了很多新类,使得 Metaspace 不断被占用,先引发 FGC ,最后导致 OOM
  5. JVM 参数设置不合理: 包括总内存大小、新生代和老年代的大小、 Eden 区和 Survivor 区的
    大小、元空间大小、垃圾回收算法等等

堆区产生的错误

堆区最容易出现的就是OutOfMemoryError错误,这种错误的表现形式有以下两种:

  1. OutOfMemoryError:GC Overhead Limit Exceeded:当JVM花太多时间执行垃圾回收、并且只能回收很少的堆空间时、就会发生此错误
  2. OutOfMemoryError:Java heap space:如果在创建新的对象时,堆内存中的空间不足以存放新创建的对象,就会引发此错误

此种情况,与配置的最大堆内存有关,且受限制于物理内存大小

元空间(MetaSpace)

用于存放类信息、常量、静态常量、JIT即时编译器编译后的机器代码等数据等/例如java.lang.Object类的原喜喜、Integer.MAX_VALUE常量等

JDK1.6:

HotSpot JVM使用Method Area方法去存储,也叫永久代(Permanent Generation)
1.方法去和"永久代(Permanent Generation)"的区别:方法去是JVM的规范。而永久代是JVM规范的一种实现,并且只有HotSpot JVM才有永久代,而对于其他类型的虚拟机,如JRockit(ORacle)、J9(IBM)并没有
2.方法区是一片连续的堆空间,当JVM加载的类信息容量超过了最大可分配空间,虚拟机会抛出OutOfMemoryError:PermGenSpace的Error
3.永久代的GC是和老年代(old generation)捆绑在一起,无论谁满了,都会出发永久代和老年代的垃圾收集
4.可以通过 -XX:PermSize=N 设置方法区(永久代)初始化空间,-XX:MaxPermSize=N 设置方法区(永久代)最大空间,超过这个值将会抛出错误:java.lang.OutOfMemoryError:PermGen

JDK1.7:

1.7是一个过度版本
将字符串常量池、静态变量转移到了堆区

JDK1.8:正式移除永久代,采用Meta Space元空间代替

元空间的本质和永久代类似,都是对 JVM 规范中方法区的一种具体实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过运行参数来指定元空间的大小。java 8 中PermGen永久代被移出HotSpot JVM的原因
1.由于PermGen内存经常会移除,容易抛出java,lang.OutOfMemoryError: PermGen错误
2.移除PermGen可以促进HotSpot JVM 与 JRockit VM 的融合,因为JRockit没有永久代

在这里插入图片描述

​ 上述运行结果可以看出,相同的代码,在JDK1.6会出现PermGen Space的永久代内存移除,而从JDK1,7和JDK1.8会出现Java heap space 堆内存移除,并且JDK1.8中PermSize和MaxPermGen参数已经无效。因此,在JDK1.7和JDK1.8中,已经将字符串常量由永久代转移到堆中,并且JDK1.8已经完全移除了永久代,采用元空间来替代

在这里插入图片描述

1.-XX:MetaspaceSize参数:主要控制Meta Space GC发生的初始阈值,也就是最小阈值,当使用的Meta Space空间到达MetaspaceSize的时候,就会触发Metaspace的GC
2.-XX:MaxMetaspaceSize参数:最大空间,默认是没有限制的。在jvm启动的时候,并不会分配MaxMetaspaceSize这么大的一块内存出来,metaspace是可以一直扩容的,知道到达MaxMetasoaceSize

在这里插入图片描述

字符串常量池

  • String的两种创建方式:

    1. 第一种方式是在常量池中获取字符串对象
    2. 第二种方式是直接在对内存空间创建一个新的字符串对象
    // 先检查字符串常量池中有没有"abc",如果字符串常量池中没有,则创建一个,然后str1指向字符串常量池中的对象,如果有,则直接将str1指向"abc"
    String str1 = "abc";
    String str2 = new String("abc");   //堆中创建一个新的对象
    String str3 = new String("abc");   //堆中创建一个新的对象System.out.printf(str1 == str2);	//false
    System.out.printf(str2 == str3);	//false
    
  • String的intern()方法:

    检查指定字符串在常量池中是否存在?如果存在,则返回地址,如果不存在,则在常量池中创建

    String s1 = new String("abc");
    String s2 = s1.intern(); //查看字符串常量池中是否存在"abc",如果存在则返回地址,如果不存在则在常量池中创建
    string s3 = "abc";  // 使用常量池中的已有的字符串常量"abc"System.out.printf(str2 == str3);	//true
    
  • String的拼接

    String s1 = "str";
    String s2 = "ing";String s3 = "str"+"ing";  // 常量池中的新字符串对象
    String s4 = str1 + str2;  // 在堆中创建的新字符串对象
    String s5 = "string";		  // 常量池中的已有字符串对象System.out.printf(str3 == str4);	//false
    System.out.printf(str3 == str5);	//true
    System.out.printf(str4 == str5);	//false
    

    在这里插入图片描述

  • String s1 = new String("abc");这句代码创建了几个字符串对象?

    创建1或2个字符串,如果常量池中已存在字符串常量"abc",则只会在堆空间创建一个字符串常量"abc"。如果常量池中没有字符串常量"abc",那么它将首先在池中创建,然后再堆空间中创建,因此将创建总共2个字符串对象
    

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

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

相关文章

JS动态转盘可自由设置个数与概率

让我为大家介绍一下转盘的实现过程与原理&#xff0c;介绍都放在下面代码块中&#xff0c;一步一步的教会你。 我们转盘使用线段来实现 <!DOCTYPE html> <html> <head><meta charset"utf-8"><title></title><style type&quo…

【理解ARM架构】异常处理

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《理解ARM架构》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 目录 ⚡ARM系统中异常与中断处理流程&#x1f362;向量表&#x1f362;保存现场&#x1f362;恢…

对一个预算有限的创业者来说,应该选择哪些形式的办公场地

对于一个预算有限的创业者来说&#xff0c;选择合适的办公场地是一个重要的决策。不同的办公场地形式有各自的优缺点&#xff0c;需要根据创业者的具体情况和需求来权衡。 一般来说&#xff0c;有以下几种常见的办公场地形式&#xff1a; - 家庭办公&#xff1a;这是最节省成本…

觉得可视化地图太难做?那你是没用过它!

后台一直有粉丝私信老李&#xff0c;问到现在各大企业对数据可视化越来越看重&#xff0c;但是感觉那些高大上的图表做起来一定很复杂甚至可能还需要一些编程基础&#xff0c;希望老李可以推荐一些简单好上手的数据可视化工具。   作为一名数据分析爱好者&#xff0c;我也尝试…

STM32之定时器--超声波测距

1、模块介绍 型号&#xff1a;HC-SR04 超声波测距模块是用来测量距离的一种产品&#xff0c;通过发送和收超声波&#xff0c;利用时间差和声音传播速度&#xff0c; 计算出模块到前方障碍物的距离。 2、超声波模块的使用方法 怎么让它发送波 Trig &#xff0c;给Trig端口至…

面试篇之微服务(一)

目录 概览 1.什么是微服务&#xff1f; 2.微服务带来了哪些挑战&#xff1f; 3.现在有哪些流行的微服务解决方案&#xff1f; 这三种方案有什么区别吗&#xff1f; 4.说下微服务有哪些组件&#xff1f; 注册中心 5.注册中心是用来干什么的&#xff1f; 6.SpringCloud可…

损失函数总结(十六):NRMSELoss、RRMSELoss

损失函数总结&#xff08;十六&#xff09;&#xff1a;MSLELoss、RMSLELoss 1 引言2 损失函数2.1 NRMSELoss2.2 RRMSELoss 3 总结 1 引言 在前面的文章中已经介绍了介绍了一系列损失函数 (L1Loss、MSELoss、BCELoss、CrossEntropyLoss、NLLLoss、CTCLoss、PoissonNLLLoss、Ga…

亚马逊云科技 re:Invent 2023:引领科技前沿,探索未来云计算之窗

文章目录 一、前言二、什么是亚马逊云科技 re:Invent&#xff1f;三、亚马逊云科技 re:Invent 2023 将于何时何地举行四、亚马逊云科技 re:Invent 2023 有什么内容&#xff1f;4.1 亚马逊云科技 re:Invent 2023 主题演讲4.2 亚马逊云科技行业专家探实战 五、更多亚马逊云科技活…

二十章 多线程

线程简介 在 Java 中&#xff0c;并发机制非常重要。在以往的程序设计中&#xff0c;我们都是一个任务完成后再进行下一个任务&#xff0c;这样下一个任务的开始必须等待前一个任务的结束。Java 语言提供了并发机制&#xff0c;程序员可以在程序中执行多个线程&#xff0c;每一…

基于Webserver的工业数据采集控制小项目

主要用到的知识点&#xff0c;http协议&#xff0c;modbus协议&#xff0c;以及进程间通信&#xff0c;消息队列&#xff0c;共享内存等 框架 数据采集 #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #…

vue+uniapp校园寻物失物招领平台 微信小程序1f6z5

系统中的核心用户是管理员&#xff0c;管理员登录后&#xff0c;通过管理员菜单来管理后台系统。主要功能有&#xff1a;首页、个人中心、用户管理、物品分类管理、物品信息管理、物品归还管理、留言板管理、系统管理等功能。管理员用例如图3-7所示。 对于本网上失物招领小程序…

Linux—进程状态

目录 一.前言 1.1.通过系统调用获取进程标示符 1.2.通过系统调用创建进程 二.进程状态 三.Z(zombie)-僵尸进程 四.僵尸进程危害 一.前言 学习进程的状态&#xff0c;我们首先了解一下进程的基本数据 1.1.通过系统调用获取进程标示符 由getpid&#xff08;&#xff09…

【Python】plt库详解和示例

plt 是 Python 中 Matplotlib 库的一个常用别名&#xff0c;它表示 pyplot&#xff0c;这是一个用于创建图形和图形的可视化表示的工具。下面是一些 plt 函数的详解和示例&#xff0c;以帮助大家理解和使用。 目录 plt.subplots&#xff08;&#xff09;plt.savefig&#xff0…

前端算法专栏-数组-75.颜色分类

介绍 Hi 大家好。我是程序员库里&#xff0c;今天新开一个前端算法专栏。 接下来会分类给大家分享常考算法题目。 很多朋友也是看着这套系列算法拿到很多offer&#xff01;所以也是想分享给更多朋友&#xff0c;帮助到有需要的朋友。 分类 数组-三路快排 题目 75. 颜色分…

Html网页threejs显示obj,ply三维图像实例

程序示例精选 Html网页threejs显示obj,ply三维图像实例 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《Html网页threejs显示obj,ply三维图像实例》编写代码&#xff0c;代码整洁&#xff0…

uniapp上架app store详细攻略

​ 目录 uniapp上架app store详细攻略 前言 一、登录苹果开发者网站 二、创建好APP 前言 uniapp开发多端应用&#xff0c;打包ios应用后&#xff0c;会生成一个ipa后缀的文件。这个文件无法直接安装在iphone上&#xff0c;需要将这个ipa文件上架app store后&#xff0c;才…

c语言-数据在内存中的存储

文章目录 1. 整数在内存中的存储2. 大小端字节序和字节序判断3. 浮点数在内存中的存储 1. 整数在内存中的存储 1.整数的2进制表示方法有三种&#xff0c;即 原码、反码和补码 2. 三种表示方法均有符号位和数值位两部分&#xff0c;符号位都是用0表示“正”&#xff0c;用1表示“…

客服管理者如何有效管理客服团队,有哪些高效方式?

在如今的市场竞争中&#xff0c;客户服务是企业成功的关键因素之一。因此&#xff0c;客服团队的有效管理至关重要。客服管理者需要了解如何有效地管理客服团队&#xff0c;以确保客户的满意度和忠诚度&#xff0c;从而提高企业的竞争力。 以下是客服管理者如何有效管理客服团队…

CSS特效020:涌动的弹簧效果

CSS常用示例100专栏目录 本专栏记录的是经常使用的CSS示例与技巧&#xff0c;主要包含CSS布局&#xff0c;CSS特效&#xff0c;CSS花边信息三部分内容。其中CSS布局主要是列出一些常用的CSS布局信息点&#xff0c;CSS特效主要是一些动画示例&#xff0c;CSS花边是描述了一些CSS…

206. 反转链表

206. 反转链表 题目&#xff1a; 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例&#xff1a; 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2&#xff1a; 输入&#xff1a;head [1…