网易(杭州研究所)初面

覆盖索引

如何实现索引覆盖?
常见的方法是:将被查询的字段,建立到联合索引里去。
InnoDB聚集索引的叶子节点存储行记录,因此, InnoDB必须要有,且只有一个聚集索引
InnoDB普通索引的叶子节点存储主键值。
举个栗子,不妨设有表:

t(id PK, name KEY, sex, flag);

画外音:id是聚集索引,name是普通索引。

表中有四条记录:

1, shenjian, m, A

3, zhangsan, m, A

5, lisi, m, A

9, wangwu, f, B
在这里插入图片描述
两个B+树索引分别如上图:
(1)id为PK,聚集索引,叶子节点存储行记录;
(2)name为KEY,普通索引,叶子节点存储PK值,即id;
既然从普通索引无法直接定位行记录,那普通索引的查询过程是怎么样的呢?

通常情况下,需要扫描两遍索引树。

例如:

select * from t where name=‘lisi’;

是如何执行的呢?
在这里插入图片描述如粉红色路径,需要扫码两遍索引树:

(1)先通过普通索引定位到主键值id=5;

(2)在通过聚集索引定位到行记录;

这就是所谓的回表查询,先定位主键值,再定位行记录,它的性能较扫一遍索引树更低。

当发起一个被索引覆盖的查询(也叫作索引覆盖查询)时,在EXPLAIN的Extra列可以看到“Using index”的信息
不是所有类型的索引都可以成为覆盖索引。覆盖索引必须要存储索引的列,而哈希索引、空间索引和全文索引等都不存储索引列的值,所以MySQL只能使用B-Tree索引做覆盖索引

如何实现索引覆盖?
select id,name,sex* from user where name=‘shenjian’;*

能够命中name索引,索引叶子节点存储了主键id,但sex字段必须回表查询才能获取到,不符合索引覆盖,需要再次通过id值扫码聚集索引获取sex字段,效率会降低。
如果把(name)单列索引升级为联合索引(name, sex)就不同了,可以避免回表。

参考:https://www.jianshu.com/p/8991cbca3854

ping实现以及对应协议

ping是定位网络通不通的一个重要手段,是用来探测本机与网络中另一台主机之间是否可达的命令,如果两台主机之间ping不通,则表明这两台主机不能建立起连接。

ping命令是基于ICMP协议来工作的,ping命令会发送一份ICMP回显请求报文给目标主机,并等待目标主机返回ICMP回显应达,如果源主机在一定时间内收到了目标主机的应答,则表明两台主机间是连通的。
举一个例子来描述ping命令工作的原理

1)假设有两个主机,主机A(192.168.0.1)和主机B(192.168.0.2),现在我们要监测主机A和主机B之间网络是否可达,那么我们在主机A上输入命令:ping 192.168.0.2;

2)此时,ping命令会在主机A上构建一个 ICMP的请求数据包,然后 ICMP协议会将这个数据包以及目标IP(192.168.0.2)等信息一同交给IP层协议;

3)IP层协议得到这些信息后,将源地址(即本机IP)、目标地址(即目标IP:192.168.0.2)、再加上一些其它的控制信息,构建成一个IP数据包;

4)IP数据包构建完成后,还不够,还需要加上MAC地址,因此,还需要通过ARP映射表找出目标IP所对应的MAC地址。当拿到了目标主机的MAC地址和本机MAC后,一并交给数据链路层,组装成一个数据帧,依据以太网的介质访问规则,将它们传送出出去;

5)当主机B收到这个数据帧之后,会首先检查它的目标MAC地址是不是本机,如果是就接收下来处理,接收之后会检查这个数据帧,将数据帧中的IP数据包取出来,交给本机的IP层协议,然后IP层协议检查完之后,再将ICMP数据包取出来交给ICMP协议处理,当这一步也处理完成之后,就会构建一个ICMP应答数据包,回发给主机A;

6)在一定的时间内,如果主机A收到了应答包,则说明它与主机B之间网络可达,如果没有收到,则说明网络不可达。除了监测是否可达以外,还可以利用应答时间和发起时间之间的差值,计算出数据包的延迟耗时。

参考:https://www.cnblogs.com/mgd666/p/14389922.html

为什么要有Time-wait状态(2MSL)

主动关闭的Socket端会进入TIME_WAIT状态,并且持报文段最大生存时间续2MSL时间长度,MSL就是maximum segment lifetime(最大分节生命期),这是一个IP数据包能在互联网上生存的最长时间,超过这个时间将在网络中消失。MSL在RFC 1122上建议是2分钟,而源自berkeley的TCP实现传统上使用30秒,因而,TIME_WAIT状态一般维持在1-4分钟。

请添加图片描述
TIME_WAIT状态存在的理由:
1)可靠地实现TCP全双工连接的终止
在进行关闭连接四路握手协议时,最后的ACK是由主动关闭端发出的,如果这个最终的ACK丢失,服务器将重发最终的FIN,因此客户端必须维护状态信息允许它重发最终的ACK。如果不维持这个状态信息,那么客户端将响应RST分节,服务器将此分节解释成一个错误(在java中会抛出connection reset的SocketException)。因而,要实现TCP全双工连接的正常终止,必须处理终止序列四个分节中任何一个分节的丢失情况,主动关闭 的客户端必须维持状态信息进入TIME_WAIT状态。

2)允许老的重复分节在网络中消逝
TCP分节可能由于路由器异常而“迷途”,在迷途期间,TCP发送端可能因确认超时而重发这个分节,迷途的分节在路由器修复后也会被送到最终目的地,这个 原来的迷途分节就称为lost duplicate。在关闭一个TCP连接后,马上又重新建立起一个相同的IP地址和端口之间的TCP连接,后一个连接被称为前一个连接的化身(incarnation),那么有可能出现这种情况,前一个连接的迷途重复分组在前一个连接终止后出现,从而被误解成从属于新的化身。为了避免这个情况,TCP不允许处于TIME_WAIT状态的连接启动一个新的化身,因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个TCP连接的时候,来自连接先前化身的重复分组已经在网络中消逝。

参考:https://blog.csdn.net/tennysonsky/article/details/48680197

TIMESTAMP和DATETIME的区别以及选择

补充:什么是UTC?

答:协调世界时,又称世界统一时间,世界标准时间,国际协调时间,简称UTC
不属于任意时区
中国大陆、中国香港、中国澳门、中国台湾、蒙古国、新加坡、马来西亚、菲律宾、西澳大利亚州的时间与UTC的时差均为+8,也就是UTC+8。
时区(Time Zone)是地球上的区域使用同一个时间定义。1884年在华盛顿召开国际经度会议时,为了克服时间上的混乱,规定将全球划分为24个时区。在中国采用首都北京所在地东八区的时间为全国统一使用时间。

对于MySQL中timestamp数据类型的特点,为什么选择timestamp类型?

答:int类型占用4字节,datetime占用8字节,timestamp占用4字节;通常情况下在选择表中列的数据类型时我们要选择能满足存储需要的,最小的数据类型,在使用MySQL数据库时有很多常见的误解,其中使用int类型来保存日期数据会提高数据读取的效率就是比较常见的一个误解。显然INT要比datetime类型小很多,同时MySQL又提供了两个非常好用的函数FROM_UNIXTIME() 和UNIX_TIMESTAMP(),使用这两个函数可以方便的在INT和DATETIME类型之间进行转换,但是使用INT类型存储时间也给我们带来了不少的麻烦:

1.数据的可读性比较差,我们在查看数据时不能直观的看出时间列中记录的一串整数所代表的时间
2.每次进行显示时都要通过函数进行转换,增加了数据使用的复杂成度。
那有没有什么更好的方法来存储日期数据呢?这就要用到我们标题中所说到的timestamp类型了,timestamp类型的特点如下:
1.存储占用 4个字节,以年月日小时分秒的日期型式显示
2.存储范围’1970-01-01 00:00:01’ to ‘2038-01-19 03:14:07’.
3.以UTC时区进行存储,但是以系统当前时间进行显示
4.可以在insert和update时把值自动更新为当前时间

由以上特点可以知道,timestamp存储占用的空间和INT类型相同,实际上timestamp类型的数据在存储时就是被保存成INT类型的数据来存储的,这和我们使用INT来存储日期时间数据可以说是完全一样的。由于同样是使用INT类型来保存数据,所以和INT类型一样其存储的时间范围也是有限制的,
**这一点大家一定要注意,超过了这个范围的日期数据建议大家使用datetime类型来保存。**另外timestamp数据存储时是以UTC时区来保存的,在显示时MySQL会自动的把数据转换为当前连接所对应时间来显示。

可见,使用timestamp来存储日期时间数据不但保证了数据类型的大小同INT类型一样,同时可以显示为日期时间格式,这在给我们使用数据带来了很多的方便。所以强烈建议大家,使用timestamp类型来存储日期数据而不要再使用INT类型了。(转自:https://www.imooc.com/article/16158

四次挥手相对三次握手多一次?

因为:客户端单方面无数据发送认为可以结束了,但是服务端不一定没有数据发送,所以服务端要将确信信息和自身发起断开分作两步

有了 IP 地址,为什么还要用 MAC 地址?

有了 IP 地址,为什么还要用 MAC 地址?
是TCP/IP协议的一部分。利用“ping”命令可以检查网络是否通畅或者网络连接速度,很好地分析和判定网络故障。

Ping发送一个ICMP(Internet Control Messages Protocol),即因特网信报控制协议;接收端回声消息给目的地并报告是否收到所希望的ICMPecho (ICMP回声应答)。它的原理是:利用网络上机器IP地址的唯一性,给目标IP地址发送一个数据包,通过对方回复的数据包来确定两台网络机器是否连接相通,时延是多少。
在这里插入图片描述

进程间的通信

管道pipe:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。

命名管道FIFO:有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。

消息队列MessageQueue:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

共享存储SharedMemory:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。

信号量Semaphore:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

套接字Socket:套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。

信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

补充:线程间的通信方式
锁机制:包括互斥锁、条件变量、读写锁
互斥锁提供了以排他方式防止数据结构被并发修改的方法。
读写锁允许多个线程同时读共享数据,而对写操作是互斥的。
条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。
信号量机制(Semaphore):包括无名线程信号量和命名线程信号量
信号机制(Signal):类似进程间的信号处理
线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。

原文链接:https://blog.csdn.net/weixin_41903587/article/details/109529691
补充:堆和栈的区别

1.管理方式不同。栈由操作系统自动分配释放,不需要我们手动控制;堆的申请和释放工作由程序员控制,因此容易产生内存泄漏。

2.空间大小不同。栈的大小一般只有8~10M,而堆有几个G。

3.生长方向不同。栈的生长方向向下,内存的地址由高到低,堆的生长方向向上,内存的地址由低到高。

4.分配方式不同。堆时动态分配的;栈有两种分配方式:静态分配和动态分配。静态分配是由操作系统完成,比如局部变量的分配。动态分配由malloc函数进行分配,但是栈的动态分配和堆是不同的,栈的动态分配是由操作系统进行释放,不需要我们手动释放。

5.分配效率不同。栈由操作系统自动分配,会在硬件层级对栈提供支持。分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是由C/C++提供的库函数或运算符来完成申请与管理,实现机制比较复杂,频繁的内存申请容易产生内存碎片。显然,堆的效率比栈低得多。

由此可见,堆和栈相比,由于大量malloc()/free()或new/delete的使用,容易造成大量的内存碎片。栈相比于堆,在程序中应用较为广泛,最常见的函数调用过程由栈来实现,函数返回地址、实参和局部变量都采用栈的方式存放。虽然栈有众多的好处,但是和堆相比不是那么灵活,有时候分配大量的内存空间任然需要用堆。总之无论是堆还是栈,在内存使用时都要防止非法越界。
参考:https://blog.csdn.net/tangya3158613488/article/details/88845180

线程并行理解

用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现。说这个话其实只有一半对,因为反应“多角色”的程序代码,最起码每个角色要给他一个线程吧,否则连实际场景都无法模拟,当然也没法说能用单线程来实现:比如最常见的“生产者,消费者模型”。

很多人都对其中的一些概念不够明确,如同步、并发等等,让我们先建立一个数据字典,以免产生误会。

多线程:指的是这个程序(一个进程)运行时产生了不止一个线程

并行与并发:
并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。

并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力。

并发与并行
线程安全:经常用来描绘一段代码。指在并发的情况之下,该代码经过多线程使用,线程的调度顺序不影响任何结果。这个时候使用多线程,我们只需要关注系统的内存,cpu是不是够用即可。

同步:Java中的同步指的是通过人为的控制和调度,保证共享资源的多线程访问成为线程安全,来保证结果的准确。如上面的代码简单加入@synchronized关键字。在保证结果准确的同时,提高性能,才是优秀的程序。线程安全的优先级高于性能。

多态

面向对象编程有三大特性:封装、继承、多态。封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据。对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法。

继承是为了重用父类代码。两个类若存在IS-A的关系就可以使用继承。,同时继承也为实现多态做了铺垫。那么什么是多态呢?多态的实现机制又是什么?请看我一一为你揭开:

所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。

程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定

基本数据类型和应用数据类型

Java中的数据类型分为两大类,基本数据类型和引用数据类型。

1、基本数据类型
基本数据类型只有8种,可按照如下分类
①整数类型:long、int、short、byte
②浮点类型:float、double
③字符类型:char
④布尔类型:boolean
2、引用数据类型
引用数据类型非常多,大致包括:
类、 接口类型、 数组类型、 枚举类型、 注解类型、 字符串型

例如,String类型就是引用类型。
简单来说,所有的非基本数据类型都是引用数据类型。

二、基本数据类型和引用数据类型的区别
1、存储位置
基本变量类型
在方法中定义的非全局基本数据类型变量的具体内容是存储在栈中的
引用变量类型
只要是引用数据类型变量,其具体内容都是存放在堆中的,而栈中存放的是其具体内容所在内存的地址
ps:通过变量地址可以找到变量的具体内容,就如同通过房间号可以找到房间一般
2、传递方式
基本变量类型
在方法中定义的非全局基本数据类型变量,调用方法时作为参数是按数值传递的
引用变量类型
引用数据类型变量,调用方法时作为参数是按引用传递的,传递的是引用的副本

调用时为temp在栈中开辟新空间,并指向book的具体内容,方法执行完毕后temp在栈中的内存被释放掉

参考:https://www.cnblogs.com/maskwolf/p/9972982.html

Java垃圾回收机制

为什么要进行垃圾回收?
随着程序的运行,内存中存在的实例对象、变量等信息占据的内存越来越多,如果不及时进行垃圾回收,必然会带来程序性能的下降,甚至会因为可用内存不足造成一些不必要的系统异常。
哪些“垃圾”需要回收?
如果某个对象已经不存在任何引用,那么它可以被回收。
在这里插入图片描述

什么时候进行垃圾回收?
引用计数算法
每个对象添加一个引用计数器,每被引用一次,计数器加1,失去引用,计数器减1,当计数器在一段时间内保持为0时,该对象就认为是可以被回收得了。(在JDK1.2之前,使用的是该算法)

缺点:当两个对象A、B相互引用的时候,当其他所有的引用都消失之后,A和B还有一个相互引用,此时计数器各为1,而实际上这两个对象都已经没有额外的引用了,已经是垃圾了。但是却不会被回收

可达性分析算法
该算法是从离散数学中的图论引入的,程序把所有的引用关系看作一张图,从一个节点GC ROOT 开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,即无用的节点
目前java 中可作为GC Root 的对象有:

虚拟机栈中引用的对象(本地变量表)
方法区中静态属性引用的对象
方法区中常量引用的对象
本地方法栈中引用的对象(Native Object)

引用计数法
给对象添加一引用计数器,被引用一次计数器值就加 1;当引用失效时,计数器值就减 1;计数器为 0 时,对象就是不可能再被使用的,简单高效,缺点是无法解决对象之间相互循环引用的问题。
可达性分析算法
通过一系列的称为 “GC Roots” 的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是不可用的。此算法解决了上述循环引用的问题。

引用的分类
JDK 1.2之后,对引用进行了扩充,引入了强、软、若、虚四种引用,被标记为这四种引用的对象,在GC时分别有不同的意义:

强引用(Strong Reference)
就是为刚被new出来的对象所加的引用,它的特点就是,永远不会被GC,除非显示的设置null,才会GC。代码如下:

Object ojb = new Object();

软引用(Soft Reference)
非必须引用,内存溢出之前进行回收。如果JVM内存并不紧张,这类对象可以不被回收,如果内存紧张,则会被回收。此处有一个问题,既然被引用为软引用的对象可以回收,为什么不去回收呢?其实我们知道,Java中是存在缓存机制的,就拿字面量缓存来说,有些时候,缓存的对象就是当前可有可无的,只是留在内存中如果还有需要,则不需要重新分配内存即可使用,因此,这些对象即可被引用为软引用,方便使用,提高程序性能。代码如下:

Object obj = new Object();

SoftReference sf = new SoftReference(obj);

obj =null;

sf.get();//有时候会返回null

这时候sf是对obj的一个软引用,通过sf.get()方法可以取到这个对象,当然,当这个对象被标记为需要回收的对象时,则返回null;

弱引用(Weak Reference)
第二次垃圾回收时回收。代码如下:

Object obj = new Object();

WeakReference wf = new WeakReference(obj);

obj =null;

wf.get();//有时候会返回null

wf.isEnQueued();//返回是否被垃圾回收器标记为即将回收的垃圾

弱引用是在第二次垃圾回收时回收,短时间内通过弱引用取对应的数据,可以取到,当执行过第二次垃圾回收时,将返回null。
弱引用主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器

虚引用(Phantom Reference)
垃圾回收时回收,无法通过引用取到对象值。代码如下

Object obj = new Object();

PhantomReference pf = new PhantomReference(obj);

obj=null;

pf.get();//永远返回null

pf.isEnQueued();//返回从内存中已经删除

虚引用是每次垃圾回收的时候都会被回收,通过虚引用的get方法永远获取到的数据为null,因此也被成为幽灵引用。虚引用主要用于检测对象是否已经从内存中删除。

扩展:如果一个对象的引用有多个,怎么通过可达性确定回收周期呢?两个原则:

单条引用链上,由最弱的一个引用类型决定
多条引用链上,由最强的一个引用类型决定
这个想想其实还是很好理解的。

原文链接:https://blog.csdn.net/w372426096/article/details/81360083

如何垃圾回收

内存主要被分为三块,新生代、旧生代、持久代。三代的特点不同,造就了他们所用的GC算法不同,新生代适合那些生命周期较短,频繁创建及销毁的对象,旧生代适合生命周期相对较长的对象,持久代在Sun HotSpot中就是指方法区(有些JVM中根本就没有持久代这中说法)。首先介绍下新生代、旧生代、持久代的概念及特点:

在这里插入图片描述
新生代:New Generation或者Young Generation。上面大致分为Eden区和Survivor区,Survivor区又分为大小相同的两部分:FromSpace 和ToSpace。新建的对象都是用新生代分配内存,Eden空间不足的时候,会把存活的对象转移到Survivor中,新生代的大小可以由-Xmn来控制,也可以用-XX:SurvivorRatio来控制Eden和Survivor的比例.

旧生代:Old Generation。用于存放新生代中经过多次垃圾回收仍然存活的对象,例如缓存对象。旧生代占用大小为-Xmx值减去-Xmn对应的值。

持久代:Permanent Generation。在Sun的JVM中就是方法区的意思,尽管有些JVM大多没有这一代。主要存放常量及类的一些信息默认最小值为16MB,最大值为64MB,可通过-XX:PermSize及-XX:MaxPermSize来设置最小值和最大值。

常见的GC算法:

标记-清除算法(Mark-Sweep)
就是分为标记和清除两个阶段进行处理内存中的对象在这里插入图片描述缺点:

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

复制算法(Copying)
将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。
当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。反复去交换两个内存的角色,完成垃圾收集
java中新生代的from和to空间就是使用这个算法

在这里插入图片描述
优点:这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等。复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。只是这种算法的代价是将内存缩小为了原来的一半,未免太高了一点。
缺点:复制收集算法在对象存活率较高时就要进行较多的复制操作,效率将会变低(所以eden区没有采用这个算法)

分代收集算法(Generational Collection)
1、根据对象存活周期的不同将内存划分为几块。
2、一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。
3、在新生代中,每次垃圾收集时都发现有大批对象死去(回收频率很高),只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。

其中,新生代又细分为三个区:Eden,From Survivor,ToSurviver,比例是8:1:1

4、老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记—清理”或者“标记—整理”算法来进行回收。

分区算法
其主要就是将整个内存分为N个多小的独立空间,每个小空间都可以独立使用,这样细粒度的控制一次回收都少个小空间和那些个小空间,而不是对整个空间进行GC,从而提升性能,并减少GC的停顿时间。

GC算法优劣标准
评价一个垃圾收集GC算法的两个标准

吞吐量(throughput)越高算法越好
暂停时间(pause times)越短算法越好

停顿
一个时间段内应用程序线程让GC线程执行而完全暂停。

垃圾回收器的任务是识别和回收垃圾对象进行内存清理,为了让垃圾回收器可以高效的执行,大部分情况下,会要求系统进入一个停顿的状态。停顿的目的是终止所有应用线程,只有这样系统才不会有新的垃圾产生,同时停顿保证了系统状态在某一个瞬间的一致性,也有益于更好地标记垃圾对象,因此垃圾回收时,都会产生应用程序的停顿

原文链接:https://blog.csdn.net/w372426096/article/details/81360083

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值