赞
踩
为什么是三次握手?不是两次、四次?
相信大家比较常回答的是:“因为三次握手才能保证双方具有接收和发送的能力。”
这回答是没问题,但这回答是片面的,并没有说出主要的原因。
在前面我们知道了什么是 TCP 连接:
用于保证可靠性和流量控制维护的某些状态信息,这些信息的组合,包括 Socket、序列号和窗口大小称为连接。
所以,重要的是为什么三次握手才可以初始化 Socket、序列号和窗口大小并建立 TCP 连接。
接下来,以三个方面分析三次握手的原因:
为什么挥手需要四次?
再来回顾下四次挥手双方发 FIN 包的过程,就能理解为什么需要四次了。
关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。
服务端收到客户端的 FIN 报文时,先回一个 ACK 应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。
从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK 和 FIN 一般都会分开发送,因此是需要四次挥手。
拥塞控制(Congestion Control)的目的是防止网络拥塞,确保网络资源被高效利用。它通过调整发送方的数据发送速率来避免网络拥塞。
流量控制(Flow Control)的目的是防止发送方发送的数据过快,导致接收方来不及处理。它通过调整发送方的数据发送速率来避免接收方的处理瓶颈。
目的:
对象:
实现方式:
拥塞控制和流量控制都是为了优化网络通信,但它们的目的和实现方式不同。拥塞控制关注于网络的整体性能,而流量控制关注于发送方和接收方之间的通信效率。在实际应用中,两者通常会结合使用,以提高通信的效率和稳定性。
在Java中,final关键字是一个非访问修饰符,它可以用来修饰类、方法和变量。final关键字的主要作用是表示一旦某个对象被初始化后,它就不能被改变。下面是final关键字在不同场景下的应用和含义:
final变量:
局部变量:当一个局部变量被声明为final时,这意味着一旦该变量被初始化后,它的值就不能被改变。
成员变量(实例变量和类变量):当一个成员变量被声明为final时,这意味着它必须被初始化,并且在对象的整个生命周期内它的值不能被改变。对于实例变量,每个对象都有一个独立的副本,且在对象的构造过程中必须被初始化。对于类变量(静态变量),必须在声明时或者在静态代码块中初始化。
常量:当final关键字与static关键字结合使用时,它可以用来定义常量。这样的常量在类中只有一个副本,并且在整个应用程序中都是相同的。
final方法:
当一个方法被声明为final时,这意味着这个方法不能被它的子类覆盖(override)。如果一个类不希望它的方法被任何继承它的类改变,那么可以将这些方法声明为final。
final类:
当一个类被声明为final时,这意味着这个类不能被继承。任何试图继承final类的操作都会导致编译错误。
在Java中,final
关键字不能用来修饰抽象类。这是因为final
和抽象(abstract
)关键字是互斥的。
final
关键字用来修饰类、方法和变量,表示不可变。如果一个类被声明为final
,则不能被继承;如果一个方法被声明为final
,则不能被重写;如果一个变量被声明为final
,则其值在初始化后不能被更改。
abstract
关键字用来修饰类或方法,表示抽象。如果一个类被声明为抽象类,则不能被实例化,必须由其子类实现所有的抽象方法;如果一个方法被声明为抽象方法,则必须在子类中实现。
由于抽象类需要被继承和实现,而final
类不能被继承,因此不能将final
用于修饰抽象类。
不需要,可以
类从加载到虚拟机中开始,直到卸载为止,它的整个生命周期包括了:加载、验证、准备、解析、初始化、使用和卸载这7个阶段。其中,验证、准备和解析这三个部分统称为连接(linking)。
类加载过程详解
1.加载
通过类的全名,获取类的二进制数据流。
解析类的二进制数据流为方法区内的数据结构(Java类模型)
创建java.lang.Class类的实例,表示该类型。作为方法区这个类的各种数据的访问入口
2.验证
验证类是否符合JVM规范,安全性检查
(1)文件格式验证:是否符合Class文件的规范(2)元数据验证 这个类是否有父类(除了Object这个类之外,其余的类都应该有父类) 这个类是否继承(extends)了被final修饰过的类(被final修饰过的类表示类不能被继承) 类中的字段、方法是否与父类产生矛盾。(被final修饰过的方法或字段是不能覆盖的) (3)字节码验证 主要的目的是通过对数据流和控制流的分析,确定程序语义是合法的、符合逻辑的。(4)符号引用验证:符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量
比如:int i = 3;字面量:3符号引用:i
3.准备
为类变量分配内存并设置类变量初始值
static变量,分配空间在准备阶段完成(设置默认值),赋值在初始化阶段完成
static变量是final的基本类型,以及字符串常量,值已确定,赋值在准备阶段完成
static变量是final的引用类型,那么赋值也会在初始化阶段完成
4.解析
把类中的符号引用转换为直接引用
比如:方法中调用了其他方法,方法名可以理解为符号引用,而直接引用就是使用指针直接指向方法。
5.初始化
对类的静态变量,静态代码块执行初始化操作
如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类。
如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。
6.使用
JVM 开始从入口方法开始执行用户的程序代码
调用静态类成员信息(比如:静态字段、静态方法)
使用new关键字为其创建对象实例
7.卸载
当用户程序代码执行完毕后,JVM 便开始销毁创建的 Class 对象,最后负责运行的 JVM 也退出内存
常用垃圾回收器:
串行垃圾收集器(Serial作用于新生代,采用复制算法;Serial Old 作用于老年代,采用标记-整理算法 )
并行垃圾收集器(JDK8默认使用此垃圾回收器,Parallel New作用于新生代,采用复制算法;Parallel Old作用于老年代,采用标记-整理算法)
CMS(并发)垃圾收集器
G1垃圾收集器
1.查询时遵循最左前缀原则
2.将范围查询放在最右侧,因为范围查询右侧的索引会失效。
原理:Hash索引使用哈希表来存储索引键和对应的记录指针。当进行索引查找时,它会计算索引键的哈希值,然后通过哈希表查找对应的记录。
优势:
劣势:
原理:B+树是一种自平衡的树结构,用于存储键值对。它将键按照某种顺序(通常是排序后的)存储在节点中,并且每个节点都可能包含多个键和子节点。
优势:
劣势:
1.和数据库建立连接
2.查询缓存(mysql8已删除)
3.语法解析和预处理得到一个新的解析树
4.查询优化与查询执行计划。使用查询优化器根据解析树生成不同的执行计划,然后选择最优的执行计划。
5.执行引擎使用执行计划去操作存储引擎。
#{}
语法:
#{}
语法是安全的,它会将参数值作为字符串处理,防止SQL注入攻击。#{}
并生成预处理语句(PreparedStatement),因此性能上会有一些开销。${}
语法:
${}
语法不安全,它会直接将参数值插入到SQL语句中,容易导致SQL注入攻击。${}
语法在Mybatis中会被解析为字符串替换,性能上相对较好,因为它不需要生成预处理语句。SELECT
语句中根据条件动态拼接列名。类加载:
分配内存:
初始化对象:
设置对象引用:
垃圾收集:
@AutoWired
@AutoWired
的默认行为是按类型自动注入。这意味着,如果Spring容器中有多个匹配类型的Bean,@AutoWired
将自动选择一个进行注入。@AutoWired
可以通过@Qualifier
注解进行配置,以指定应该注入哪个Bean。@AutoWired
是自动装配的一种形式,通常用于字段、构造器和方法。@AutoWired
需要进行类型匹配,因此它的性能可能会稍微低于@Resource
。@Resource
@Resource
的默认行为是按名称自动注入。这意味着,如果Spring容器中有多个匹配类型的Bean,@Resource
将自动选择一个具有指定名称的Bean进行注入。@Resource
不支持通过@Qualifier
注解进行配置。如果需要按名称注入,@Resource
需要直接指定Bean的名称。@Resource
不支持自动装配,它总是通过名称进行注入。@Resource
不需要进行类型匹配,它的性能通常优于@AutoWired
。1、完全基于内存的,C语言编写
2、采用单线程,避免不必要的上下文切换可竞争条件
3、使用I/O多路复用模型,非阻塞IO
发布/订阅模式:
列表(List):
发布/订阅与列表的组合:
与RabbitMQ/Kafka等常规MQ的区别:
Redis实现消息队列的优缺点:
Redis实现的消息队列功能简单且快速,适用于对实时性要求高且数据量不大的场景。如果你需要一个持久化、高吞吐量的消息队列,那么RabbitMQ或Kafka可能是更好的选择。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。