每天一套面试题Day8-金证股份
1. SpringBoot相比Spring的优势
主要优势:
- 简化配置:自动配置,减少XML配置(Spring Boot的自动配置本质上就是自动创建和配置Bean,比如DataSource,JdbcTemplate)
- 内嵌服务器:内置Tomcat、Jetty等,无需单独部署
- 起步依赖:starter依赖简化依赖管理
- 快速开发:大大减少开发时间和配置工作
2. 动态代理
两种实现方式:
- JDK动态代理:基于接口实现,使用
Proxy和InvocationHandler - CGLIB动态代理:基于继承实现,可以代理没有接口的类
应用场景: Spring AOP、事务管理、日志记录等
3. Redis数据结构
经典五种,String,Hash,适合对象的存储,Set,适合存放不重复的集合,比如共同关注,Zset,带有数字分数的集合,可以自动排序,适合存储班级排名等,List,适合存放有序的,有先后顺序的, BitMap,位图,存储二值,适合比如签到打卡 Stream,用于消息队列 GEO,找周围位置
+HyperLogLog,提供不精确的去重计数。在输入元素的数量或者体积非常非常大时,计算基数所需的内存空间总是固定的、并且是很小的。传统统计UV的问题:需要记录每个用户的ID,用户量巨大时内存消耗大。UV(Unique Visitor)即独立访客数,是指一段时间内访问网站的不同用户的数量 String,分布式锁,计数器 List,消息队列 GEO,读[ˈdʒiːəʊ]
作者:我是猫熊 链接:https://www.nowcoder.com/discuss/813538728458088448?sourceSSR=users 来源:牛客网
4. HTTP状态码
常见状态码:
- 2xx:成功
- 200 OK
- 3xx:重定向
- 301 永久重定向
- 302 临时重定向
- 4xx:客户端错误
- 400 Bad Request 语法错误
- 401 Unauthorized 未认证(不知道你是谁)
- 403 Forbidden 权限不够(知道你是谁但是你没有权限)
- 404 Not Found
- 5xx:服务器错误
- 500 Internal Server Error
- 503 Service Unavailable
5. MySQL索引底层
B+树索引特点:
- 非叶子节点只存储键值,不存储数据
- 叶子节点包含所有数据,形成有序链表
- 支持范围查询和排序
- 树高度较低,查询效率稳定
6. HashMap底层,扩容机制
数组+链表 数组+链表/红黑树(JDK8以及之后,在 ?时会变成红黑树 当元素数目大于因子(0.75)×?的时候,会发生扩容,扩容为原来的两倍,在jdk7之前要重新计算来确定位置,由于要么位置在原位置,要么在原位置+原数组长度,所以用哈希值与上原数组长度,如果为真,那么就在原位置+原数组长度,不然的话就不动。确定好在哈希桶的位置后,再尾插进对应的位置。
默认初始容量16,负载因子0.75,当元素数量超过(容量×负载因子)发生扩容。链表长度>=8且数组长度≥64时会转为红黑树,提升查询效率。
作者:我是猫熊 链接:https://www.nowcoder.com/discuss/813538728458088448?sourceSSR=users 来源:牛客网
7. JVM内存模型,线程不安全场景
JVM内存区域: 分为线程共享和不共享的。线程共享的有:堆,存放对象实例;方法区,存放类型信息,比如说类的修饰符,全限定名,字段信息,方法信息,即时编译的??还有final修饰的,字符串常量在JDK7以及之前也放在方法区中,后面考虑到内存管理的方便,所以放在了堆中。线程不共享的区域,也就是随线程生而生,随线程灭而灭的有程序计数器,存放指向当前命令的指针?虚拟机栈,存放方法的局部变量和形参,本地方法栈,和虚拟机栈类似,但是对应的是native方法
程序计数器存放的是当前线程正在执行的指令的地址(或偏移量),而不是指向当前命令的指针。 方法区有即时编译器(Just-In-Time Compiler)编译后的代码缓存(将热点代码编译成本地机器码),方法信息(方法的字节码),运行时常量池(编译期生成的各种字面量,声明为 final 的常量值)
作者:我是猫熊 链接:https://www.nowcoder.com/discuss/813538728458088448?sourceSSR=users 来源:牛客网
线程不安全场景:
- 复合操作(如先检查再操作,先读后写)
- 简单的++,(因为实际上包含三个步骤,读取,修改,写入)
- 指令重排序
- 内存可见性问题
线程不安全的根本原因: 可见性:一个线程的修改对其他线程不可见 原子性:操作被中途打断 有序性:指令重排序导致意外结果
8. 线程池创建和参数
创建方式:
ExecutorService executor = Executors.newFixedThreadPool(10);
// 或
ThreadPoolExecutor executor = new ThreadPoolExecutor(
corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
核心参数:
- corePoolSize:核心线程数
- maximumPoolSize:最大线程数
- keepAliveTime:空闲线程存活时间
- workQueue:工作队列
- ThreadFactory:线程工厂
- RejectedExecutionHandler:拒绝策略
9. TCP与UDP的区别
10. 监控SQL慢查询
监控方法:
- 开启MySQL慢查询日志
- 数据库连接池监控:Druid监控(通过一个内置的Web页面)
11. 缓存穿透、击穿、雪崩
缓存穿透:
- 问题:查询不存在的数据,绕过缓存直接访问数据库
- 解决:布隆过滤器、缓存空值
缓存击穿:
- 问题:热点key过期瞬间,大量请求直接访问数据库
- 解决:设置逻辑过期,互斥锁
缓存雪崩:
- 问题:大量key同时过期,导致数据库压力激增
- 解决:随机过期时间、高可用(主从复制,哨兵,集群
12. volatile关键字
特性:
- 保证可见性:一个线程修改后,其他线程立即可见(用了volatile,改在工作内存(比如CPU缓存)里面改后马上刷回主内存)
- 禁止指令重排序:防止JVM优化重排
- 不保证原子性:复合操作仍需同步
应用场景:
- 状态标志位(简单的布尔状态控制)
- 双重检查锁单例模式
- 独立观察 - 多个线程观察独立状态
链接
#面试真题#坚持就是胜利
查看20道真题和解析