Java高频面试题

时间:2023-03-08 22:09:49
Java高频面试题

网络相关

1.http1.0和http1.1的区别?

http1.0每次请求都需要和服务器建立一个TCP连接,服务器完成请求后立即断开TCP连接。

  http1.1支持长连接,客户端在http请求头上加上Connection=Keep-Alive时,告诉服务器处理完本次请求后保持连接。Connection=close时告诉服务器返回本次请求结果后关闭连接。

2.http和https的区别?

  1.http数据传输是明文的,https是在http的技术上增加了SSL协议使数据传输加密

  2.http默认端口是80,https是443

  3.http是无状态的,https ssl基于证书验证服务器身份

3.TCP三次握手和四次握手的流程,为什么断开连接是四次,如果握手只有两次会出现什么?

  三次握手:

  1.客户端发送syn(同步确认包)包到服务器,等待服务器确认

  2.服务器收到syn包,必须确认sync包然后发送syn+ack报文给客户端

  3.客户端收到服务端的syn+ack,向服务器发送ack包,建立连接

  四次挥手:

  1.客户端发送一个FIN报文请求关闭连接

  2.服务器收到这个FIN,然后发送一个ACK确认收到

  3.服务器在数据传输完成之后,发送一个FIN给客户端

  4.客户端收到FIN,发送ACK确认

  为什么是四次:服务器收到客户端的FIN报文时,仅仅表示客户端没有数据再发送给服务端了,但是服务端可能还有数据没有完整发送给了客户端,所以不会马上关闭socket连接,等数据发送完毕后再发送FIN报文给客户端,

  告诉客户端同意关闭连接。

  如果握手只有两次,可能出现因为网络问题客户端没有收到服务端的syn+ack包,导致连接没有建立成功。

  

三次握手:
A:“喂,你听得到吗?”A->SYN_SEND

B:“我听得到呀,你听得到我吗?”应答与请求同时发出 B->SYN_RCVD | A->ESTABLISHED

A:“我能听到你,今天balabala……”B->ESTABLISHED

四次挥手:
A:“喂,我不说了。”A->FIN_WAIT1

B:“我知道了。等下,上一句还没说完。Balabala…..”B->CLOSE_WAIT | A->FIN_WAIT2

B:”好了,说完了,我也不说了。”B->LAST_ACK

A:”我知道了。”A->TIME_WAIT | B->CLOSED

A等待2MSL,保证B收到了消息,否则重说一次”我知道了”,A->CLOSED

4.TCP/IP如何保证可靠性,数据包有哪些数据组成?

  1.校验和

  发送的数据包的二进制相加然后取反,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段。

  2.确认应答+序列号

  TCP给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。

  3.超时重传

  当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。

  4.流量控制

  TCP连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP使用的流量控制协议是可变大小

  的滑动窗口协议。

  接收方有即时窗口(滑动窗口),随ACK报文发送

  5.拥塞控制

  当网络拥塞时,减少数据的发送。

  发送方有拥塞窗口,发送数据前比对接收方发过来的即使窗口,取小

  慢启动、拥塞避免、拥塞发送、快速恢复

5.http get请求和post请求的区别?以及数据包格式?

  1.get请求是向服务端请求数据,post是向服务端提交数据

  2.get请求参数拼装在url上只支持url编码,post请求参数在请求报文中

  3.get请求发送一个数据包,post发送两个数据包

6.长连接和短连接?

  1.1.0客户端向服务端发送请求建立连接,请求结束就关闭连接,1.1支持设置connection:keep-alive,还有超时时间建立长连接,下次请求继续用当前连接,不用新建连接

  

7.TIME_WAIT和CLOSE_WAIT?

  TIME_WAIT:表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。

  CLOSE_WAIT:这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是查看你是否还有数据发送给对方,如果没有的话,那么你也就可以close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。

8.说出你知道的几种http响应码?

  200 ok

  302重定向

  404没找到请求资源

  406请求无法接受

  500服务器内部错误

  502 网关错误

缓存相关

1.redis持久化的几种方式,优缺点是什么,怎么实现的?

  RDB和AOF

2.redis的缓存失效策略?

  定期删除+惰性删除

  1.定期删除,每100ms起一个线程扫描全部的key,发现过期,删除

  2.查询到这个key的时候先判断有没有设置有效期有没有过期,过期的话删除。

3.缓存穿透和缓存雪崩的解决办法?

  1.缓存穿透:指查询一个数据库中一定不存在的数据。比如传入商品编号去查询数据库,数据库中不存在。解决方案是查询到的即使为空的对象也设置缓存,有效期设置短一点,比如60秒。

  2.缓存雪崩:在某个时间段,缓存集中过期失效。解决方案:

    1.加锁排队,在缓存失效后通过加锁或者队列来控制数据库写缓存的 线程数量。使用mutex, 在缓存失效的时候,不是去立即查询数据库而是用SETNX设置一个mutex key,当返回key设置成功后再去查询数据库并回设缓存,设置失败可能是其他线程已经查询数据库重设了缓存就重试get缓存的方法

    2.数据预热,通过缓存reload机制,预先去更新缓存,在即将大并发访问前手动触发加载缓存不同的key,再设置不同的过期时间,让缓存失效的时间点尽量均匀

    3.做二级缓存:a1为原始缓存,a2为备份缓存,a1失效时可以访问a2,a1缓存的有效时间设置为短期,a2为长期

    4.缓存永远不过期:1.不设置过期时间  2.把过期时间存在key的value中,发现要过期了,通过后台线程进行缓存的更新。

  3.缓存击穿:key是个热点数据,扛着高并发请求集中对这个key进行访问,在这个key失效的瞬间,持续的高并发就穿破缓存直接请求数据库,解决方案:

    1.使用互斥锁(mutex key)
    业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,

    而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,

    当操作返回成功时再进行load db的操作并回设缓存;否则,设置失败可能是其他线程已经查询数据库重设了缓存, 就重试整个get

    缓存的方法。
    2.缓存永远不过期:1.不设置过期时间  2.把过期时间存在key的value中,发现要过期了,通过后台线程进行缓存的更新

4.redis集群,高可用,原理?

5.mysql里有20万条数据,如何保证redis中的数据都是热点数据?

  使用allkeys-lru淘汰策略

6.redis的数据淘汰策略?

  1.allkeys-lru:删除最近最少使用的一部分key(LRU less recentley used )

  2.allkeys-random:随机删除一部分key

  3.volatile-lru:在设置了过期时间的key中,删除最近最少使用的一部分key

  4.volatile-random:在设置了过期时间的key中,随机删除一部分key

  5.noeviction:不删除策略,达到最大内存直接返回错误信息

  6.volatile-ttl:在设置了过期时间的key中,优先删除剩余时间(time to live)短的key

7.redis的并发竞争问题如何解决?了解redis事务的CAS操作吗?

数据库相关

1.MySql InnDB存储的文件结构?

MySql使用使用文件系统的目录和文件来保存数据库和表的定义。innodb的数据存储在表空间中,表空间是由innodb管理的一个黑盒子,由一系列的数据文件组成。

2.索引树是如何维护的?

3.数据库自增主键可能的问题?

4.MySql的几种优化?

5.MySql为什么使用B+树?

1.B+树的每个叶子节点都包含指向下一个节点的指针,从而方便叶子节点的范围遍历

2.B+树对索引列是顺序组织存储的,所以很适合查找范围数据

6.数据库锁表的相关处理?

7.索引失效的场景?

1.查询中的列不是独立的,则mysql就不会使用索引。如对列使用了表达式和函数

2.联合索引不符合最左查询原则

3.

8.高并发下如何做到安全的修改同一行数据,乐观锁和悲观锁是什么?InnDB的行级锁有哪两种,解释其含义?

通过行锁来实现,inndb默认行锁。

乐观锁:持乐观态度,读取数据认为不会用其他线程修改本条数据,因此不加锁。修改数据通过版本号或者cvs来控制。

悲观锁:持悲观态度,读和写都加锁。

9.数据库会死锁吗,举一个例子,mysql如何解决死锁?

会死锁,如:两个事物同时修改同样的两行数据,只是修改顺序相反,可能出现都执行了第一条update语句,同时也锁定了该行数据,接着每个事物都去尝试执行第二条update语句,发现已被对方锁定,则出现了死锁。

解决方案:数据库系统实现了各种死锁检测和死锁超时机制,如inndb检测到死锁依赖,并立即返回一个错误。inndb目前解决方案是,将持有最少行级排它锁的事物进行回滚。

10.为什么select *会影响性能

1.首先数据库要知道*是什么,先查询数据字典(记录数据库和应用程序元数据的目录),增大开销

2.多出一些不用的列,可能不在索引的覆盖范围,同时增加传输时间

3.影响数据库自动重写优化sql

11.索引的优点,即索引为什么能加快查询

1.索引大大减少了服务器需要扫描的数据量

2.索引可以帮助服务器避免排序和临时表

3.索引可以讲随机io变为顺序io

分布式相关

1.接口的幂等性概念?

2.消息中间件如何解决消息丢失的问题?

3.对分布式事务的理解?

4.如何实现负载均衡,有哪些算法可以实现?

  https://i.cnblogs.com/EditPosts.aspx?postid=10578883

5.zookeeper的用途,选举的原理是什么?选举的时候能提供服务吗?

6.zookeeper的原理和适用场景?

7.zookeeper的watch机制?

8.redis/zk节点宕机如何处理?

9.分布式集群下如何做到唯一序列号?

10.如何做一个分布式锁?

11.用过哪些MQ,怎么用的?和其他MQ比有什么优缺点,MQ的连接是线程安全的吗?

12.MQ系统的数据如何保证不丢失?

13.列举你能想到的数据库分库分表策略;分库分表后,如何解决全表查询的问题?

14.什么是线程死锁,如何解决

产生死锁的条件有四个:

  1. 互斥条件:所谓互斥就是进程在某一时间内独占资源。

  2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

  3. 不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。

  4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

线程死锁是因为多线程访问共享资源,由于访问的顺序不当所造成的,通常是一个线程锁定了一个资源A,而又想去锁定资源B;在另一个线程中,锁定了资源B,而又想去锁定资源A以完成自身的操作,两个线程都想得到对方的资源,而不愿释放自己的资源,造成两个线程都在等待,而无法执行的情况。

要解决死锁,可以从死锁的四个条件出发,只要破坏了一个必要条件,那么我们的死锁就解决了。在java中使用多线程的时候一定要考虑是否有死锁的问题哦。

  1、按顺序加锁

  上个例子线程间加锁的顺序各不一致,导致死锁,如果每个线程都按同一个的加锁顺序这样就不会出现死锁。

  2、获取锁时限

  每个获取锁的时候加上个时限,如果超过某个时间就放弃获取锁之类的。

  3、死锁检测

  按线程间获取锁的关系检测线程间是否发生死锁,如果发生死锁就执行一定的策略,如终断线程或回滚操作等。