面试高频问题----1

发布于:2024-06-05 ⋅ 阅读:(49) ⋅ 点赞:(0)

一、Spring的启动流程

1.spring容器初始化:spring Bean配置加载;创建和配置ApplicationContext
2.spring容器刷新:BeanDefinition加载;BeanFactory后处理器执行;Bean后处理器注册
3.Bean实例化:实例化单例Bean;依赖注入;Bean属性设置;Bean初始化
4.BeanPostProcessor:Bean初始化前后处理
5.应用程序上下文刷新完成:ApplicationContext初始化完成事件;处理器和监听器启动
6.运行阶段:应用程序启动并运行;事件驱动机制
7.销毁阶段:容器关闭;Bean销毁

二、Mysql为什么使用B+树?

1.高效的范围查询:B+树的叶子节点构成一个有序链表,提高了查询效率;
2.减少磁盘I/O:B+树的节点大小设置的足够大,可以减少树的高度,使得大部分查询操作可以在一次磁盘I/O中完成;
3.适合磁盘存储:B+树的节点通常比较大,可以容纳更多的键值对,减少了树的高度,从而减少了磁盘I/O次数;
4.支持高并发:B+树的插入、删除和查找操作都是在节点上进行的局部操作,由于B+树的平衡性,节点调整次数相对较少,避免了锁的粒度过大,提高了数据库的并发能力
5.顺序访问性能好:B+树的叶子节点构成有序链表,可以通过顺序遍历叶子节点来实现高效的顺序访问。

三、zset底层实现

Redis zset的底层实现通过跳表和哈希表来提供高效的有序集合操作;跳表用于维持元素的有序性,支持范围查询和顺序操作;哈希表用于快速查找元素和分数,保证O(1)的查找效率。
****跳表:跳表是一种用于快速查找、插入和删除的数据结构,具有与平衡树相似的事件复杂度。Redis用跳表来维护zset中的有序元素;
跳表的特性:1.多层链表:跳表由多层链表组成,每一层都是一个有序链表。最底层包含所有元素,而上层是下层的抽样;
                      2.查找效率:查找元素时,从顶层开始,如果当前元素的下一个元素值大于查找值就向下一层移动,否则就在当前层移动;
                      3.空间效率:跳表在平均情况下只需要额外的O(N)空间。
****哈希表:哈希表用于快速查找元素是否存在以及获取元素的分数。哈希表存储元素成员与分数的映射。

四、Mysql索引

索引失效
1.查询条件中有or,即使有部分条件带索引也会失效
2.like查询是以%开头
3.索引列上参与计算会导致索引失效
4.违背最左匹配原则
5.如果mysql估计全表扫描要比使用索引要快,会不适用索引
索引的优缺点
优势:可以快速检索,减少I/O次数,加快检索速度;根据索引分组和排序,可以加快分组和排序;
劣势:索引本身也是表,因此会占用存储空间,一般来说,索引表占用的空间的数据表的1.5倍;索引表的维护和创建需要时间成本,这个成本随着数据量增大而增大;构建索引会降低数据表的修改操作(删除,添加,修改)的效率,因为在修改数据表的同时还需要修改索引表

五、什么是volatile关键字?

volatile是轻量级的同步策略,volatile通常修饰的是字段,synchronized通常修饰的是方法或代码块
从原理上来讲:volatile是告诉CPU对它进行读写时要特殊对待,保证内存的可见性,而synchronized配合上锁的机制保证一段代码在某一时刻只能被一个线程执行完。
保证可见性不保证原子性:
volatile很好的保证了变量的可见性变量经过volatile修饰后,对此变量进行写操作时,汇编指令中会有一个LOCK前缀指令:
1.将当前处理器缓存行的数据写回到系统内存
2.这个写回内存的操作会使得在其他处理器缓存了该内存地址无效
什么意思呢?意思就是说当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值,这就保证了可见性。
volatile与原子性:因为volatile它不是锁只是一个变量修饰符,所以无法保证原子性。Java中只有对基本类型变量的赋值和读取是原子操作. 如果一个变量被volatile修饰了,那么肯定可以保证每次读取这个变量值的时候得到的值是最新的,但是一旦需要对变量进行自增这样的非原子操作,就不会保证这个变量的原子性了。
可见性,排序性和原子性的底层原理:
重排性:
volatile可以禁止指令重排,这就保证了代码的程序会严格按照代码的先后顺序执行。这就保证了有序性。编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。
volatile与原子性:
因为volatile它不是锁只是一个变量修饰符,所以无法保证原子性
可见性:
如果一个变量被volatile所修饰的话,在每次数据变化之后,其值都会被强制刷入主存。而其他处理器的缓存由于遵守了缓存一致性协议,也会把这个变量的值从主存加载到自己的缓存中。这就保证了一个volatile在并发编程中,其值在多个缓存中是可见的。

网站公告

今日签到

点亮在社区的每一天
去签到