蔚来JAVA面试(收集)

发布于:2024-03-28 ⋅ 阅读:(28) ⋅ 点赞:(0)

先叠加,这个是自己找的答案不一定对,只是给我参考看看而已。

一、项目

这个没有,根据实际项目情况来。蔚来比较喜欢拷打项目,所以要对项目非常熟悉(慌)

二、JAVA基础

2.1 Java中的IO模型有用到过吗?了解过NIO、BIO、AIO

阻塞:当一个线程正在处理的时候,其他线程会被挂起

非阻塞:当一个线程正在处理的时候,其他线程可以去干其他的事情

同步:当发送请求的时候,只有服务器端响应完了,才可以返回

非同步:发送一个请求的寿,立即得到服务器端的回应,但是没有结果,结果在后续计算。

BIO:是同步且阻塞的模型

NIO:同步非阻塞

AIO 异步非阻塞的

2.2ArrayList,LinkedList,HashMap优缺点,实现原理

ArrayList:底层是数组,名为elementData的数组。优点适合遍历获取值,通过下表获取是o(1)的复杂度,缺点:删除和增加需要移动后续的值。ArrayList是懒初始化,在不new之前,是不会分配空间的,只有在你new了之后,才会默认分片10大小,当空间不足的时候会调用ensureCapacity(int minCapacity)1.5倍,创建一个新数组,然后让旧的数组在拷贝到新的数组,实现randomdata,支持随机获取值,并且是快速失败,即是在用迭代器尽情迭代的时候,我们不可以对其进行修改。是因为里面有个modcount,当我当前值不等于modCount,则会抛出异常。

LInkedLIst:底层是通过链表实现的,使用的是双向链表,在这里面有size,last.first,Nodel类适合插入和删除值,然后获取值需要通过遍历。

HashMap:1.7之前是数组、链表,之后变成数组、链表、红黑数。在数组大于=64,链表大于等于8的时候会自动进行成红黑树,当链表小于=6的时候退化成数组。

三、JVM

3.1 说一下jvm的gc机制

gc即是垃圾回收机制,我们先说下我们垃圾回收有俩种-计数器分析,

3.2 java内存模型

java的内存模型又叫做JMM,早期jvm底层不一样,无法统一,为了屏蔽底层的不同点,于是引入了java内存模型。他有主内存和工作内存。线程只在工作内存中执行。变量则是放在主内存中,工作内存通过复制主内存这个变量的地址放在工作内存中进行修改。让后再放入主内存中。

3.3 java内存区域? 

有线程私有的:程序计数器:存放当前执行的字节码对应的行号,本地方法栈,虚拟机栈

非私有的:堆、方法区

3.4 OOM异常? OOM和SOF区别? 

oom:全名over out memory,申请的栈大小超过可用内存会抛出oom

sof:全名Stack over Flow,申请的内大小超过jvm虚拟机的大小

3.5 G1和CMS的对比

 GMS:是一种获取最短停顿时间为目标的收集器。基于并发“标记清理”实现,在标记清楚过程中不会导致用户线程无法定位引用对象。只作用于老年代

初始标记,并发标记,重新标记,并发清楚

CMS优点:支持并发手机,低停顿

CMS缺点:CMS收集器对cpu的资源非常敏感,在并发阶段虽然不会导致用户线程停顿,但是由于占用了一部分cpu,在cpu不足的时候会出现卡顿

无法清除浮动垃圾,在执行并发清楚的时候,用户线程也会产生一部分可回收对象,但是这部分对象只有在下一次回收的时候才会被清楚

清理后会产生内存碎片

使用场景:垃圾回收最短的停顿时间,针对老年代不频繁gc的场景

G1:

初始标记、根区间扫描、并发标记、最终标记、筛选回收

优点:G1充分发挥多核功能,使用多cpu来缩短stop-the-world时间

分代手机:G1能够自己管理不同分代内已创建对象和新对象的手机

G1从整体上是标记整理,局部则是复制。大内存机器

四、SQL 

4.1 慢sql的优化

首先mysql不会自动开启慢查询,我们需要通过 slow-query-log 进行开启,里面可以设置slow-query-time,定位低效率的sql,explain分析执行计划,关键列有table:设计到哪些表、type:显示是哪些连接,all,index,rang,ref,ref-eq,const,ROW:需要扫描的行数

key:使用的索引。

4.2 做过分库分表吗?说一下你的理解

1、分表

(1)垂直分表

表中的字段较多,一般将不常用的、 数据较大、长度较长的拆分到“扩展表“。一般情况加表的字段可能有几百列,此时是按照字段进行数竖直切。注意垂直分是列多的情况。

(2)水平分表

单表的数据量太大。按照某种规则(RANGE,HASH取模等),切分到多张表里面去。 但是这些表还是在同一个库中,所以库级别的数据库操作还是有IO瓶颈。这种情况是不建议使用的,因为数据量是逐渐增加的,当数据量增加到一定的程度还需要再进行切分。比较麻烦。

2、分库

(1)垂直分库

一个数据库的表太多。此时就会按照一定业务逻辑进行垂直切,比如用户相关的表放在一个数据库里,订单相关的表放在一个数据库里。注意此时不同的数据库应该存放在不同的服务器上,此时磁盘空间、内存、TPS等等都会得到解决。

(2)水平分库

水平分库理论上切分起来是比较麻烦的,它是指将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据集合不同。 水平分库分表能够有效的缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源等的瓶颈。

4.3 mysql不同隔离级别、索引底层 

 mysql:写未提交、写已提交、可重复读、串行化。mysql默认的则是可重复读,它解决了脏读、不可重复读,但是没有解决幻读。最后他是通过next-key-lock解决了。

索引的底层:锁引是通过B+树进行的,分页每次16KB,在主键索引中存放的是这条记录,然后在二级索引中则存放的是这条记录的key。

4.4 mysql常用函数

 sum():求和

max():求最大值

ifnull():如果这个值是null,则

distinict:去重复

4.5 解释下mysql的脏读、不可重复读、幻读

脏读:即是用户在操作数据库的时候,读取到了用户另一个还没有提交的事务。这是在mysql的读未提交才会发生这种事情。

不可重复读:就是在一个事务中,我用户执行一个select的指令,过了一段时间,再次执行一样的指令,结果值出现了不同。读未提交,读已提交都会发生

幻读:就是在一个事务中,用户在读取数据,无法查询到这个数据,但是另一个事务插入了一个id=5的数据,然后a事务也插入id=5的数据,会提示报错,但是查询该表数据的时候,却无法查询到他。就像一个幻影一样。

 4.6 索引失效的场景有哪些

1.当mysql认为全局查询比索引查询好的时候。比如说我给用户的性别建索引,大量相同数据。

2.索引的靠左原则。

3.执行or指令的时候,其中一个字段不是索引字段

4.执行like% ,和l%ike%的时候,但是也不是绝对的,只是在大部分的情况下,如果当前表中字段只有主字段和二级字段,则会走索引。

5.数据的强制转换

6.在查询时做聚合操作。

4.7  Explain执行计划用过吗

关键列有

table:设计到哪些表、

type:显示是哪些连接,all,index,rang,ref,ref-eq,const,

ROW:需要扫描的行数

key:使用的索引。

4.8 Type字段有哪一些

table:设计到哪些表、

type:显示是哪些连接,all,index,rang,ref,ref-eq,const,

ROW:需要扫描的行数

key:使用的索引。

4.9 binlog和redolog的区别

redolog和binlog都是mysql的日志文件。

relog用来保证mysql的持久化,他是一个环,只可以适用于宕机,如果是要恢复到很早之前的数,relog是无法做到的。因为他是环,永远都是一个空间,当空间不足的时候,他会自动回收掉之前最久的数据。

binlog则是保证mysql在主从复制的时候,从节点可以拷贝获取到和主节点一样的数据。binlog里面的数据不会被清楚,当空间不足的时候,会自己创建文件,重新指向

 4.10 索引分类,其他分类方式

按数据结构:B+.map.fulltext

按物理逻辑:主键索引、二级索引

按字段:单列索引、联合字段

按字段特性:唯一索引、主键索引、字段索引、普通索引

4.11 b+树好处和查找过程

 首先b+的好处,他是有序的,是二叉搜索书,即左边的节点小于主节点,右边的节点大于主节点,便于查找。其次他的除了叶子节点其他地方不会存放数据,索引当读取页单位的时候16K,会读取的更多,就查找目标对象更快。其次就是还实现了范围查询。

4.4 MVCC  

五、Redis

5.1分布式锁加锁时如何避免影响效率

分布式情况下们,对同一个商品的下单请求,会导致所有的客户端必须对同一个库存锁key佳锁,一旦被锁住之后,就会变成串行化,无法处理大批次的问题。

我们可以采用分库存的方式,即是将库存分成多个数据,然后自己写一个随机算法,导航到不同的库存,就类似于银行多开窗口。当钱库存库存不足的时候,应该立即释放锁,然后随机到另一个库存中试图加锁。这样子就提高了效率。

5.2说一下redis的特点

 1.速度快:因为位于内存之间

 2.有多种多样的数据类型,String,LIst,Map,Set,Zset,Bitmap

 3.单线程执行指令,减少了线程切换带来的不必要的消耗

 4.多路复用,采用linux的思想通过select,epoll,实现多路复用,允许有多个安全套接请求,和已连接请求。

 5.3 说一下redis中的缓存穿透、缓存击穿、缓存雪崩

 缓存穿透:指访问redis和数据库中没有的数据,解决方法:设置空缓存,但是空缓存会占用redis的空间,所以最好设置下过期时间,通过布尔过滤器,布尔过滤器是map解决的,通过crc16进行运算。

缓存击穿:指一个热数据,突然过期,数据打到了数据库上。解决方案给这个key进行加锁,等我创建好之后,我再释放。2.设置热点数据永远不过其

缓存雪崩:有俩种情况一种是同一时刻大量key都过期了,我们要设置的就是随机分配key的过期时间,这样子就不会发生数据同时过期。还有就是热数据永远不过期。另一种是redis宕机了,这时候我们可以通过哨兵,选举出一个新的主节点,这样子也可以解决,

 5.4  redis怎么做主从、集群

主从模式是三种模式中最简单的,在主从复制中,数据库分为两类:主数据库(master)和从数据库(slave)。

其中主从复制有如下特点:

  • 主数据库可以进行读写操作,当读写操作导致数据变化时会自动将数据同步给从数据库

  • 复制的数据流是单向的,只能由主节点复制到从节点。

  • 从数据库一般都是只读的,并且接收主数据库同步过来的数据

  • 一个master可以拥有多个slave,但是一个slave只能对应一个master

  • slave挂了不影响其他slave的读和master的读和写,重新启动后会将数据从master同步过来

  • master挂了以后,不影响slave的读,但redis不再提供写服务,master重启后redis将重新对外提供写服务

  • master挂了以后,不会在slave节点中重新选一个master

工作机制:当从节点启动的时,主动向主节点发送sync连接请求。主节点接收到sync命令后在后台保存快照(rdb持久化)和缓存保存快照这段时间的命令,然后将保存的快照文件和缓存的命令发送给slave。slave接收到快照文件和命令后加载快照文件和缓存的执行命令。复制初始化后,master每次接收到的写命令都会同步发送给slave,保证主从数据一致性。

1)在配置文件中加入slaveof{masterHost}{masterPort}随Redis启动生效。

2)在redis-server启动命令后加入--slaveof{masterHost}{masterPort}生效。

3)直接使用命令:slaveof{masterHost}{masterPort}生效。

节点有一对一,主要是做故障转移操作。一对多:主节点做写,从节点做读。多对多,主节点可以将数据给从节点,从节点将自己的数据给更从的节点

可以有效降低主节点负载和需要传送给从节点的数据量。

复制原理:

1)保存主节点(master)信息。执行slaveof后从节点只保存主节点的地址信息便直接返回,这时建立复制流程还没有开始。

2)从节点(slave)内部通过每秒运行的定时任务维护复制相关逻辑,当定时任务发现存在新的主节点后,会尝试与该节点建立网络连接。从节点会建立一个socket套接字,专门用于接受主节点发送的复制命令。

3)发送ping命令。连接建立成功后从节点发送ping请求进行首次通信,ping请求主要目的如下:

  • 检测主从之间网络套接字是否可用。

  • 检测主节点当前是否可接受处理命令。

如果发送ping命令后,从节点没有收到主节点的pong回复或者超时,比如网络超时或者主节点正在阻塞无法响应命令,从节点会断开复制连接,下次定时任务会发起重连。

4)权限验证。如果主节点设置了requirepass参数,则需要密码验证,从节点必须配置masterauth参数保证与主节点相同的密码才能通过验证;如果验证失败复制将终止,从节点重新发起复制流程。

5)同步数据集。主从复制连接正常通信后,对于首次建立复制的场景,主节点会把持有的数据全部发送给从节点,这部分操作是耗时最长的步骤。Redis在2.8版本以后采用新复制命令psync进行数据同步,原来的sync命令依然支持,保证新旧版本的兼容性。新版同步划分两种情况:全量同步和部分同步。

6)命令持续复制。当主节点把当前的数据同步给从节点后,便完成了复制的建立流程。接下来主节点会持续地把写命令发送给从节点,保证主从数据一致性。

全量复制:

发送psync命令进行数据同步,由于是第一次进行复制,从节点没有复制偏移量和主节点的运行ID,所以发送psync-1。

2)主节点根据psync-1解析出当前为全量复制,回复+FULLRESYNC响应。

3)从节点接收主节点的响应数据保存运行ID和偏移量offset。

4)主节点执行bgsave保存RDB文件到本地。

5)主节点发送RDB文件给从节点,从节点把接收的RDB文件保存在本地并直接作为从节点的数据文件。对于数据量较大的主节点,RDB文件从创建到传输完毕消耗的总时间超过repl-timeout所配置的值(默认60秒),从节点将放弃接受RDB文件并清理已经下载的临时文件,导致全量复制失败。Redis支持无盘复制,生成的RDB文件不保存到硬盘而是直接通过网络发送给从节点,通过repl-diskless-sync参数控制,默认关闭。无盘复制适用于主节点所在机器磁盘性能较差但网络带宽较充裕的场景。

6)对于从节点开始接收RDB快照到接收完成期间,主节点仍然响应读写命令,因此主节点会把这期间写命令数据保存在复制客户端缓冲区内,当从节点加载完RDB文件后,主节点再把缓冲区内的数据发送给从节点,保证主从之间数据一致性。如果主节点创建和传输RDB的时间过长,对于高流量写入场景非常容易造成主节点复制客户端缓冲区溢出。默认配置为client-output-buffer-limit slave256MB64MB60,如果60秒内缓冲区消耗持续大于64MB或者直接超过256MB时,主节点将直接关闭复制客户端连接,造成全量同步失败。

7)从节点接收完主节点传送来的全部数据后会清空自身旧数据。

8)从节点清空数据后开始加载RDB文件,对于较大的RDB文件,这一步操作依然比较耗时。对于线上做读写分离的场景,从节点也负责响应读命令。如果此时从节点正出于全量复制阶段或者复制中断,那么从节点在响应读命令可能拿到过期或错误的数据。对于这种场景,Redis复制提供了slave-serve-stale-data参数,默认开启状态。如果开启则从节点依然响应所有命令。对于无法容忍不一致的应用场景可以设置no来关闭命令执行,此时从节点除了info和slaveof命令之外所有的命令只返回“SYNC with master in progress”信息。

9)从节点成功加载完RDB后,如果当前节点开启了AOF持久化功能,它会立刻做bgrewriteaof操作,为了保证全量复制后AOF持久化文件立刻可用。

部分:

部分复制的流程:

1)当主从节点之间网络出现中断时,如果超过repl-timeout时间,主节点会认为从节点故障并中断复制连接。

2)主从连接中断期间主节点依然响应命令,但因复制连接中断命令无法发送给从节点,不过主节点内部存在的复制积压缓冲区,依然可以保存最近一段时间的写命令数据,默认最大缓存1MB。

3)当主从节点网络恢复后,从节点会再次连上主节点。

4)当主从连接恢复后,由于从节点之前保存了自身已复制的偏移量和主节点的运行ID。因此会把它们当作psync参数发送给主节点,要求进行部分复制操作。

5)主节点接到psync命令后首先核对参数runId是否与自身一致,如果一致,说明之前复制的是当前主节点;之后根据参数offset在自身复制积压缓冲区查找,如果偏移量之后的数据存在缓冲区中,则对从节点发送+CONTINUE响应,表示可以进行部分复制。

6)主节点根据偏移量把复制积压缓冲区里的数据发送给从节点,保证主从复制进入正常状态。

5.5  有序集合的底层数据结构使用的是?

跳表加字典

5.6  跳表插入数据的过程能描述一下吗

5.7 拒绝策略有几种?说了4种,反问还有其他的吗

ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。 ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务 ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务

线程池的默认拒绝策略为AbortPolicy,即丢弃任务并抛出RejectedExecutionException异常。

5.8 你常用的拒绝策略是哪种,为什么

六、锁 

 6.1原子操作和加锁操作的区别是什么

锁操作是一种数据结构

6.2 java中的锁,synchronized和reentrantlock原理以及如何选择 

synchronized原理

ynchronized 是JVM层面的锁,是Java关键字,通过monitor对象来完成(monitorenter与monitorexit),对象只有在同步块或同步方法中才能调用wait/notify方法,ReentrantLock 是从jdk1.5以来(java.util.concurrent.locks.Lock)提供的API层面的锁。

ReentrantLock原理

重入锁ReentrantLock,顾名思义,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁,而不会造成自己阻塞自己。重进入是指任意线程在获取到锁之后能够再次获取该锁而不会被锁所阻塞。 ReentrantLock虽然没能像synchronized关键字一样支持隐式的重进入,但是在调用lock()方法时,已经获取到锁的线程,能够再次调用lock()方法获取锁而不被阻塞。 除此之外,该锁的还支持获取锁时的公平和非公平性选择。实际上,公平的锁机制往往没有非公平的效率高,但是,并不是任何场景都是以TPS作为唯一的指标,公平锁能够减少“饥饿”发生的概率,等待越久的请求越是能够得到优先满足。 公平性锁保证了锁的获取按照FIFO原则,而代价是进行大量的线程切换。非公平性锁虽然可能造成线程“饥饿”,但极少的线程切换,保证了其更大的吞吐量。 在Java里一共有两类锁, 一类是synchornized同步锁,还有一种是JUC里提供的锁Lock,Lock是个接口,其核心实现类就是ReentrantLock。 ReentrantLock主要利用CAS+AQS队列来实现 ,主要是采用自旋锁,循环调用CAS操作来实现加锁,避免了使线程进入内核态的阻塞状态。 CAS :Compare and Swap,比较并交换。CAS有3个操作数:内存值V、预期值A、要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。该操作是一个原子操作,被广泛的应用在Java的底层实现中。在Java中,CAS主要是由sun.misc.Unsafe这个类通过JNI调用CPU底层指令实现

ReentrantLock和synchronized区别

可重入性:两者的锁都是可重入的,差别不大,有线程进入锁,计数器自增1,等下降为0时才可以释放锁 锁的实现 :synchronized是基于JVM实现,操作系统级别(用户很难见到,无法了解其实现),ReentrantLock是JDK实现的,可以查到到对应实现的源码。 公平锁 :synchronized只能是非公平锁。而ReentrantLock可以实现公平锁和非公平锁两种。 超时设置 :synchronized不能设置超时,而Lock可以设置超时。 中断等待 :synchronized不能中断一个等待锁的线程,而Lock可以中断一个试图获取锁的线程。 性能区别 :在最初的时候,二者的性能差别差很多,当synchronized引入了偏向锁、轻量级锁(自选锁)后,二者的性能差别不大,官方推荐synchronized(写法更容易、在优化时其实是借用了ReentrantLock的CAS技术,试图在用户态就把问题解决,避免进入内核态造成线程阻塞) 功能区别 :

  • 便利性:synchronized更便利,它是由编译器保证加锁与释放,不会产生死锁。ReentrantLock是需要手动释放锁,所以为了避免忘记手工释放锁造成死锁,所以最好在finally中声明释放锁。
  • 锁的细粒度和灵活度,ReentrantLock优于synchronized

ReentrantLock独有的功能

  • 可指定是公平锁还是非公平锁,所谓公平锁就是先等待的线程先获得锁
  • 提供了一个Condition类,可以分组唤醒需要唤醒的线程
  • 提供能够中断等待锁的线程的机制,lock.lockInterruptibly()

ReentrantLock 和synchronized应该怎么选?

从上边的介绍,看上去ReentrantLock不仅拥有synchronized的所有功能,而且有一些功能synchronized无法实现的特性。性能方面,ReentrantLock也不比synchronized差,那么到底我们要不要直接使用ReentrantLock放弃使用synchronized呢?答案是不要这样做。 J.U.C包中的锁定类是用于高级情况和高级用户的工具,除非说你对Lock的高级特性有特别清楚的了解以及有明确的需要,或这有明确的证据表明同步已经成为可伸缩性的瓶颈的时候,否则我们还是继续使用synchronized。相比较这些高级的锁定类,synchronized还是有一些优势的,比如synchronized不可能忘记释放锁。还有当JVM使用synchronized管理锁定请求和释放时,JVM在生成线程转储时能够包括锁定信息,这些信息对调试非常有价值,它们可以标识死锁以及其他异常行为的来源。在确实需要一些 synchronized 所没有的特性的时候,比如时间锁等候、可中断锁等候、无块结构锁、多个条件变量或者轮询锁。 ReentrantLock 还具有可伸缩性的好处,应当在高度争用的情况下使用它,但是请记住,大多数 synchronized 块几乎从来没有出现过争用,所以可以把高度争用放在一边。我建议用 synchronized 开发,直到确实证明 synchronized 不合适,而不要仅仅是假设如果使用 ReentrantLock “性能会更好”。总之,如果需要实现ReenTrantLock的三个独有功能时,就选择使用ReenTrantLock, 通常情况下synchronized就能够满足了,而且使用起来简单,由JVM管理,不会产生死锁。

七、多线程 

  7.1讲一下对线程池的理解

线程池(本文特指ThreadPoolExecutor类)顾名思义,就是一个装了线程的池子。线程池创建和管理若干线程,在需要使用的时候可以直接从线程池中取出来使用,在任务结束之后闲置等待复用,或者销毁。
线程池中的线程分为两种:核心线程和普通线程。核心线程即线程池中长期存活的线程,即使闲置下来也不会被销毁,需要使用的时候可以直接拿来用。而普通线程则有一定的寿命,如果闲置时间超过寿命,则这个线程就会被销毁。

7.2 讲一下对线程池的理解(线程池的四大参数)
    - 加入说核心线程数为0,最大线程也为0,这个时候添加一个线程,会出现什么情况

核心线程数,最大线程数,生存时间,生存时间单位、队列名字、阻塞队列、策略,看策略

 八、spring

 8.1 说一下Spring中的IOC?底层是如何实现的

OC是一种设计模式,它是依赖注入(Dependency Injection,DI)的一种实现方式。在Spring框架中,IOC是一种用于实现依赖注入的技术,它可以帮助开发人员更好地管理和组织代码,提高代码的可重用性和可维护性。

OC底层主要是使用xml解析+反射+工厂模式实现,通过源码分析总结如下:

首先容器的创建过程,用到工厂模式BeanFactor接口的实现类DefaultListableBeanFactory创建bean工厂,先bean工厂设置一些参数(比如前置处理BeanPostProcessor、Aware接口)

然后通过加载解析bean对象,xml配置或者注解@Autowired,也就是准备定义BeanDifinition对象,这里也是解析xml配置

接下来就是一些扩展点的处理,也是BeanFactoryPostProcessor的处理包括展占位符处理PlaceholderConfigurerSupport(BeanFactoryPostProcessor子类),处理${password}等。

再通过反射(xml配置获取到全类名,得到Class对象,调用newInstance就可创建对象,BeanDifinition对象实例化成具体的bean对象,也就是先实例化,然后在初始化bean对象,填充属性,调用aware子类的方法,调用BeanPostProcessor前置处理,调用init-method,调用BeanPostProcessor后置处理。

初始化完成就,开始获取完整bean对象,getBean(),使用完成就如果要销毁就调用destroyMethod。

8.2 spring的io和aop

九.设计模式

9.1 熟悉什么设计模式,选择几个讲一下怎么用的

单例模式。单例模式是给一个全局的切入口偶,让大家只可以通过这个切入点进行访问,并且或许的对象是一致的。常用的话,就有spring里面bean的创建默认就是单例模式的
 

十 算法

10.1 拓扑排序 

10.2 快排

10.3 归并

10.4 三个线程交替打印ABC

10.5 力扣 22 括号生成

10.6 LCR 030. O(1) 时间插入、删除和获取随机元素

10.7 有1亿个浮点数,如果找出第5大? 

模板:大数据中 TopK 问题的常用套路🎈 | Java八股文面试网 – Java2Top.cn

10.8  二叉树的最近公共父节点

10.9 股票最大回撤率 

10.10 三数之和 

10.11 判断是否平衡二叉树

10.12 LeetCode接雨水

十一、其他 

11.1   springboot和spring区别

1、Spring Boot提供极其快速和简化的操作,让 Spring 开发者快速上手。

2、Spring Boot提供了 Spring 运行的默认配置。

3、Spring Boot为通用 Spring项目提供了很多非功能性特性。

11.2 springboot和springcloud区别

pringboot和springcloud的区别主要是:1.作用不同;前者的作用是为了提供一个默认配置,从而简化配置过程;后者的作用是为了给微服务提供一个综合管理框架。2.使用方式不同;前者可以单独使用;springcloud必须在springboot使用的前提下才能使用。springboot和springcloud都是从spring生态圈中衍生出来的软件开发框架,但是二者的创作初衷是完全不同的,springboot的设计目的是为了在微服务开发过程中可以简化配置文件,提高工作效率,而springcloud的设计目的是为了管理同一项目中的各项微服务,因此二者是完全不同的两个软件开发框架。
springcloud的组成部分包括哪些?
第一,注册发现中心(Eureka)。它的作用是将同一个项目中的各个微服务注册到一起,从而使它们间相互认识。
第二,调用中心(Fegin)。它的作用是将各个微服务联系起来,使它们之间可以实现相互调用,由此组合成一个整体。
第三,熔断器(Hystrix)。它的作用是当某个微服务瘫痪时可以将它从调用链中踢除出去,从而保证调用链上其他微服务的正常运作。
第四,微服务网关(Zuul)。它的作用是为不同的微服务提供一个统一的访问端口。
第五,云配置中心(Cloud Config)。它的作用是将一个项目所需的配置文件都放到云端统一管理,从而做到一个项目只有一套配置文件。
第六,消息总线(Cloud Bus)。它的作用是在修改配置文件时,可以在不停止服务运行的情况下重新加载配置

11.3 nacos注册中心底层使用的协议?

在 Nacos 在 1.x 版本的时候,服务注册是通过 Http 接口实现的

2.x 版本相比于 1.x 版本最主要的升级就是客户端和服务端通信协议的改变,由 1.x 版本的 Http 改成了 2.x 版本 gRPC

Nacos 客户端在启动的时候,会通过 gRPC 跟服务端建立长连接

这个连接会一直存在,之后客户端与服务端所有的通信都是基于这个长连接来的

当客户端发起注册的时候,就会通过这个长连接,将服务实例的信息发送给服务端

服务端拿到服务实例,跟 1.x 一样,也会存到服务注册表

除了注册之外,当注册的是临时实例时,2.x 还会将服务实例信息存储到客户端中的一个缓存中,供 Redo 操作

谓的 Redo 操作,其实就是一个补偿机制,本质是个定时任务,默认每 3s 执行一次

这个定时任务作用是,当客户端与服务端重新建立连接时(因为一些异常原因导致连接断开)

那么之前注册的服务实例肯定还要继续注册服务端(断开连接服务实例就会被剔除服务注册表)

所以这个 Redo 操作一个很重要的作用就是重连之后的重新注册zhezhe,

后续再补充,背的脑子大了,八股全背忘了背混了,要思维导图消化了唉 

本文含有隐藏内容,请 开通VIP 后查看