前言
多次面试中遇到的自己比较记忆深刻,但是不太会的问题,做一个总结,持续更新...
鼠鼠我五月初才开始全力准备找实习,然后5月18号投递,陆续开始面试,因为准备时间短,深度和广度都达不到,并且没什么做的很透的项目,所以感觉暑期实习有点无望。
这里总结一下最近面试中遇到的一些比较印象深刻的问题,希望大家共勉。
我的想法是,大家可以直接在评论区作答,然后互相交流一下,然后后期可以出一个提供答案的版本。
个人感悟:我们看八股文的时候能看懂的程度远远不够,因为很多内容光解释清楚就得写上千字,因此回答需要精简有力,让面试官体会到你是理解且懂的,这需要很高的融会贯通和语言表达能力。因此在回答问题的时候,尽量按照面试时候可能的回答来练习,希望不要直接复制粘贴一大段或者一篇文章,当然可以给好文章的链接。
面试题
- synchronized优化有哪些?
- 红黑树为什么比平衡二叉树更优,差别主要在哪?
- Java垃圾回收机制安全点SafePoint了解吗?
- Spring框架中,一个http请求打到Controller上的流程是什么,请求的生命周期或者处理流程?
- Spring中Java Bean的生命周期
- 在SpringBoot项目中,如何使用Redis的zset实现一个排行榜
- 你对函数式编程有什么了解?
- TCP/IP的七层结构分别是什么,每一层的功能是什么?
- Maven是干什么的?
- 讲一讲进程和线程的区别?协程了解吗?
- 谈谈你对JVM的理解
- 谈谈你对堆和栈的认识和理解?
- 假如我在函数体内,创建了一个变量Integer a,它是在栈上还是在堆上?
- JVM垃圾回收的流程讲一下
- 讲一下类加载机制。
- http状态码有哪些?301和302有什么区别,501、502、503、504有什么区别?
- 对象头了解吗,对象头、实例数据、对齐填充。
- InnoDB是如何解决幻读问题的?(Next-Key锁:间隙锁+行锁)
- 有一个微博大V,它发送一条消息,如何将这条消息推送到每个关注他的用户?(读扩散、写扩散问题)
- 线程池核心线程会回收吗,比如核心线程数是2,最大线程数5,我创建了一个线程,执行完毕后这个线程会回收吗?
- 如果有很大的并发量,但是每个线程的执行时间都很短,使用什么线程池比较合适?
- HashMap中使用拉链法/红黑树来处理哈希冲突,什么时候链表变换为红黑树,红黑树是否会收缩为链表?
- Netty的IO多路复用是如何实现的,讲一下!
- 为什么Redis使用单线程?
- 垃圾回收器有哪些?CMS垃圾回收器的过程。如果你设计或选择一个垃圾回收器,你需要考虑哪些问题?
- CAP了解吗,Spring Cloud呢?
- 详细介绍一下类加载的过程。
- MySQL数据库事物的四个隔离级别,是如何实现可重复读的(MVCC),具体如何实现的?
- 我们实现一个审批系统,经销商会提交审批清单,会有多个管理员同时进行审批,如何保证管理员审批的清单不会出现冲突,你会如何设计?
- Java的一个特点是支持多线程,难道C/C++不支持么?有什么区别?
- 方法重载在JVM层是如何实现的?
- CPU的三级缓存了解吗?
- NIO和AIO的本质区别是什么?
- synchronized是如何保证原子性的?(执行synchronized时,对应lock原子操作会刷新工作内存中共享变量的值)
- synchronized是如何保证可见性的?
- synchronized是如何保证有序性的?(加synchronized之后,依然会发生重排序,只不过,我们有同步代码块,可以保证一个线程执行同步代码中的代码,保证有序性)
- synchronized是可中断的吗?
- synchronized出现异常会释放锁吗?(会释放锁)
- synchronized和Lock的区别是是什么?
- 为什么说之前版本的synchronized是重量级锁?
- 一个请求发送到Controller,然后调用Service,执行了方法A,而方法A调用了方法B,方法B是被AOP增强的方法,假如方法B执行失败,抛出异常,是否会回滚?
- 一个MySQL数据表,有一个列为a,并建立了索引,里面存储数据1到10,假如我执行SQL语句
select * from table where str(a)='3',是否会执行成功,是否会走索引,执行过程和结果是什么? - 在SpringBoot中@EnableAutoConfiguration是如何实现自动配置的?
- 如何解决分布式Session问题?
- 多线程问题,两个子线程轮流打印。
- Redis是怎么实现内存优化的?
- jdk1.7到1.8有哪些变化?
- 谈谈你对tcp粘包的理解,如何解决这种问题?
- 你作为学生会主席,你觉得相对于其他人你有什么优势?
- 你在写项目的过程中,遇到过哪些困难,有没有这样的case,你是怎么解决的?
- netty有了解吗,谈谈你的理解?
- 现在用户登陆都是使用邮箱登陆或者手机号登陆,谈谈整个实现过程?
- 如何传输大文件?
- 为什么要使用LocalDate、LocalTime或LocalDateTime?
- 在使用MySQL语句中,使用
order by desc的效率怎么样,有没有优化的方法? - 序列化和反序列化有了解吗,你有使用过哪些序列化工具吗?
- ConcurrentHashMap是线程安全版本的HashMap,为什么HashMap允许插入null的key和value,而ConcurrentHashMap不允许插入null的key和value,为什么会这样设计,谈谈你的理解?此外,ConcurrentHashMap是线程安全的,在多线程情况下一定没有问题吗?从CAP理论角度探讨这个问题。
- volatile底层是如何实现的?
- 说明一下浏览器中输入URL执行流程?
- 你了解WebSocket协议吗?
- https中的s是什么意思,可以详细说一下过程吗,以及为什么要这么设计,谈谈你的理解?
- 你对线程池的理解,为什么要使用线程池?
题目答案
待补充...
-
synchronized优化有哪些? synchronized是JDK的一个关键字,JDK6对其进行了一个较大的优化,包括偏向锁、轻量级锁、(重量级锁)、锁粗化、锁消除、自旋锁。
-
synchronized和Lock的区别是是什么?
- synchronized是关键字,而Lock是一个接口
- synchronized会自动释放锁,而Lock必须手动释放锁
- synchronized是不可中断的,Lock可以中断也可以不中断
- 通过Lock可以知道线程有没有拿到锁,而synchronized不能
- synchronized能锁住方法和代码块,而Lock只能锁住代码块
- Lock可以使用读写锁提高多线程读效率
- synchronized是非公平锁,而Lock可以实现非公平锁和公平锁
- Java垃圾回收机制安全点SafePoint了解吗?
GC并不是任何时候都能做的,需要代码运行到安全点或安全区域才能进行。特定的安全点位置主要有以下几种:
- 方法返回之前
- 调用某个方法之后
- 抛出异常的位置
- 循环的末尾
当垃圾收集需要中断的线程的时候,不直接对线程操作,仅仅简单设置一个标志位,各个线程执行过程时在上面所说的那些安全点都会检查这个标志,一旦发现中断标志位为真时,就在安全点上主动挂起。
安全区域就是一个区域内都可以执行垃圾回收的区域。
- Spring框架中,一个http请求打到Controller上的流程是什么,请求的生命周期或者处理流程?
第一,http请求一般是一个域名,需要请求DNS域名服务器解析,转换为IP地址,当然存在本地缓存,则直接取缓存。
第二,向目标IP地址发送http请求,一般情况下这个http请求是一个反向代理服务器如nginx,nginx需要做负载均衡,将请求转发到特定的目标服务器上(微服务是怎么弄的不太清楚,后续再改进)。
第三,http请求发送到Web服务器,Web服务器负责解析http请求与返回http响应。
第四,转发请求到Servlet容器处理,主要组件是一系列的过滤器Filter
第五,请求转发到Spring容器的DispatcherServlet,找到匹配的HandlerExecutionChain和HandlerAdapter,经过一系列的过滤器Interceptor,然后再打到Controller上。
第六,执行上述过程的后置操作,整个过程为一个类似于栈的后进先出U形返回过程。
5 Spring中Java Bean的生命周期(待优化)
加载Bean:使用反射机制从特定的文件加载Bean的字节码
实例化Bean:new创建Bean对象,填充属性,初始化,主要涉及一些Bean装配的前置和后置操作
添加到单例池:添加Bean到singleObjets,供全局使用。
销毁:执行销毁的前置方法和销毁方法
- 在SpringBoot项目中,如何使用Redis的zset实现一个排行榜
需要注意的两点:
- 数据库一致性问题
- 如何选定zset的key以实现特定时间段内的排行榜
简单说一下解决措施:
1)使用版本号机制确保数据库一致性,在MyBatis Plus中可以使用@Version来实现。
2)始终维护当前时间起,一个小时内的排行榜,维护一个zset,其key为"redis::current",虽有插入数据的过期时间设置为1小时,这样可以保证删除超过一小时的数据缓存。
3)构建历史排行榜,如近3小时,近24小时,分别创建key为"redis::three-hours"和"redis::one-day",每次整点时刻,将key为"redis::current"的zset的数据添加到"redis::three-hours"和"redis::one-day"的zset中,并设置过期时间分别增加2小时和23小时。
4)这样,每次查询排行榜时,调用ZREVRANGE查看排行榜即可。
具体实现见SpringBoot项目代码。
-
你对函数式编程有什么了解?
Java中的lambda表达式,stream()流式计算 -
TCP/IP的七层结构分别是什么,每一层的功能是什么?
-
有一个微博大V,它发送一条消息,如何将这条消息推送到每个关注他的用户?(读扩散、写扩散问题)
这里有两个博客记录了聊天软件的设计方案,涉及到该问题。
IM群聊消息究竟是存1份(即扩散读)还是存多份(即扩散写)
读扩散,写扩散,终于讲清楚了! -
线程池核心线程会回收吗,比如核心线程数是2,最大线程数5,我创建了一个线程,执行完毕后这个线程会回收吗?此时重新提交一个线程任务,如何执行?
核心线程不会回收,此时新提交一个任务,由于当前线程池中的线程数量小于核心线程数,会创建新的线程来执行最近提交的任务。 -
HashMap中使用拉链法/红黑树来处理哈希冲突,什么时候链表变换为红黑树,红黑树是否会收缩为链表?
有两种情况可能出发红黑树退化为链表:
- 扩容时resize()时,如果红黑树中节点的数量小于等于6,则退化为链表
- 移除元素remove()时,判断红黑树根为空或红黑树根左/右子树为空,或左子树的左子树为空,则退化为链表
-
为什么说之前版本的synchronized是重量级锁?
加锁存在用户态和内核态切换。 -
谈谈你对tcp粘包的理解,如何解决这种问题?(待补充) tcp是一个流式透明传输的协议,对于一个tcp链接,发送端将多个数据包如a、b和c连续发送到接收端,在tcp传输中是无差别的字节流传输,接收端无法区分出数据包a、b和c的,这样接收到的数据包就无法正常使用,这就是粘包问题。粘包问题不是tcp协议本身的问题,而是上层协议或程序员的工作,需要区分数据包的间隔,将传输层的数据包正确解析出来。
解决方案有以下:
- 使用标准的应用层协议(http https)来封装要传输的不定长的数据包。
- 在每条数据的尾部添加特殊字符,如果遇到特殊字符,代表当条数据接收完毕。
- 在发送数据块之前,在数据块最前边添加一个固定大小的数据头,这时候数据由两部分组成:数据头+数据块
- 说明一下浏览器中输入URL执行流程?
graph TD
解析协议 --> 解析域名
解析域名 --> 解析端口号
解析端口号 --> 解析路径
解析路径 --> 传递查询字符串
传递查询字符串 --> 解析锚点
解析锚点 --> 请求资源
请求资源 --> 接收资源