楼主一年经验的Java后端,2021年初毕业,3月份入职某互联网大厂,2022年5月份不幸毕业,之后面试了一些公司,也拿到了还算能接受的offer,近期趁着有空,将面经回馈大家,大家一起交流学习。
总体和外企篇区别也不大,可能对于技术基础的考察更深一点,不考察英语
国内互联网大厂对于技术的考察比较深入和详细,考察的点包括数据库原理、Java基础、JVM垃圾回收机制、多线程和高并发,这方面考察的比较多。对于校招时候重点准备的计算机网络很少提及,操作系统被问过几次,但是不多。我的技术栈写了Redis,所以这一部分也被问的比较多,包括缓存雪崩、缓存击穿、缓存穿透以及Redis的底层存储结构都被问过。
面试官一般会关注自己比较熟悉的或者和面试岗位关系密切的项目。另外据我观察高并发场景是大家都比较喜欢问的,如果有相关的项目可以着重准备。
简历书写方面建议在项目经历中突出一些技术点,这样可以让面试官顺着我们的技术点来考察,避免无差别攻击。
mid为主
这家通过了但是没有去,给钱很大方,不过不太适合我
问项目细节
写算法题:一个二叉树的最长路径,路径返回来(LeetCode上有很类似的一个题,是求最长路径的长度,这里的题目是要把路径返回来,所以相当于是一个变式)
场景题:跟我之前从事的业务相关的一个题
业务题:对于X(面试部门的业务)的理解,与Y(其他几家相似的业务)有什么区别
算法题:
一个字符串,只包含小写字母。对字母进行去重之后会产生一系列的子序列,返回字典序最小的子序列的第一个字母。
解法:用一个Set存储已经遍历了的字母,用一个字符变量tmp存储当前已遍历到的最小的字母。从后往前遍历,如果当前字母小于tmp,tmp替换成当前字母,并且将当前字母塞入Set,如果当前字母大于tmp,判断是否已经在Set中,如果已经在了说明后面有可以替换的,如果不在Set中,tmp替换成当前字母,并且将当前字母塞入Set。最后的结果就是tmp。
主要问项目,没有考察算法题
面了两个部门,都挂了以后还是有别的部门捞,但是没有再面了
(1)问项目
项目难点。
问中间件的细节。HSF的细节。生产者的IP变了怎样让消费者感知到。
项目中某个消息的QPS大概多大,存在哪里,数据库的QPS多大
(2)算法题
连续出了三道题。。。
带过期时间的LRU缓存(LeetCode146)。写了一半说思路。
给定一个数组,找出这个数组的和为奇数且和最大的子序列。说了思路
给定一堆字符串,找出在所有字符串中都出现了的字符。说了思路
(3)基础
TCP三次握手
数据库连接池的作用
还有别的,有点忘记了
(4)程序设计
如果让你设计一个RPC框架,你要怎样设计(针对增加机器和减少机器的情况)
(当天进行了很多面试,具体问题记不太清了,可能有一些不是字节问的)
(1)基础相关
数据库的分页管理
64M的内存,数据每条1k,可以存多少
13层的B+树最多可以存多少数据
数据库一页可以存多少数据,是由什么决定的
(补充一个别家面试:数据库的某一页剩下一些零散的内存,怎么把它们迁移出去得到一个完整的页
B+树和B树的区别
B+树的存储结构
(别家面试:红黑树的底层实现、左旋右旋构建
Redis为什么这么快
IO复用、底层存储结构
线程同步的方式
(别家面试:synchronized的底层实现原理
(别家面试:spring和springBoot的区别
spring的线程同步。
AOP的底层实现原理
(2)算法题:
1~n共n个数,找到按字典序排序的第k个(LeetCode440),是一个hard,没做出来挂了。
这次是一个业务部门
1)项目相关
用的什么垃圾回收机制
新生代是ParNew,老年代是cms
业务数据指标还了解哪些
Tair(某个公司自研中间件)锁用的哪种数据结构
2)技术基础
JVM垃圾回收机制
数据库的索引失效
设计模式:发布订阅模式
3)算法题
LRU缓存(LeetCode164)这个题被问了好几次了,在不同的公司被问了好几次
这家是我面的第一家互联网公司,面的特别惨,很多都没答上来。一面结束觉得自己凉了,不过隔了一周又被捞了,但是最后还是挂了,可能是综合评价不够好吧。
下面记录的是一面的面试题,因为面的太差面完了把答案也整理进来了,二面主要就问了一些项目相关的内容,和我之前的工作经历相关性比较大,不太具有普适性,就不写了。
可见性:
可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
volatile关键字 和 synchronized关键字都实现了可见性。
如果不限制可见性,多个线程读取数据时,可能直接读取各自缓存中的数据,当同时修改的时候可能会读到脏数据,加入可见性之后要求只能在内存中读取数据,这样一个线程改动了数据,其他的线程马上就可以知道。
原子性:
即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
命令的不可拆分
有序性:
即程序执行的顺序按照代码的先后顺序执行。禁止指令重排序
volatile关键字 和 synchronized关键字保证了有序性。
多个指令在执行的过程中,Java会按照耗时等指标进行重新排序,有序性限制使得该指令之前的指令一定在该指令之前,该指令之后的一定会在该指令之后。
在java 1.5的java.util.concurrent.atomic包下提供了一些原子操作类,即对基本数据类型的 自增(加1操作),自减(减1操作)、以及加法操作(加一个数),减法操作(减一个数)进行了封装,保证这些操作是原子性操作。atomic是利用CAS来实现原子性操作的(Compare And Swap),CAS实际上是利用处理器提供的CMPXCHG指令实现的,而处理器执行CMPXCHG指令是一个原子性操作。
计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入。由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存在一个问题,由于CPU执行速度很快,而从内存读取数据和向内存写入数据的过程跟CPU执行指令的速度比起来要慢的多,因此如果任何时候对数据的操作都要通过和内存的交互来进行,会大大降低指令执行的速度。因此在CPU里面就有了高速缓存。
也就是,当程序在运行过程中,会将运算需要的数据从主存复制一份到CPU的高速缓存当中,那么CPU进行计算时就可以直接从它的高速缓存读取数据和向其中写入数据,当运算结束之后,再将高速缓存中的数据刷新到主存当中。
如果一个变量在多个CPU中都存在缓存(一般在多线程编程时才会出现),那么就可能存在缓存不一致的问题。
为了解决缓存不一致性问题,通常来说有以下2种解决方法:
1)通过在总线加LOCK#锁的方式
2)通过缓存一致性协议
这2种方式都是硬件层面上提供的方式。
JAVA内存模型:
在Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来屏蔽各个硬件平台和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果。
Java内存模型规定所有的变量都是存在主存当中(类似于前面说的物理内存),每个线程都有自己的工作内存(类似于前面的高速缓存)。线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作。并且每个线程不能访问其他线程的工作内存。
(1)在Java中,对基本数据类型的变量的读取和赋值操作是原子性操作,即这些操作是不可被中断的,要么执行,要么不执行。 如果要实现更大范围操作的原子性,可以通过synchronized和Lock来实现。
(2)对于可见性,Java提供了volatile关键字来保证可见性。当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。 另外,通过synchronized和Lock也能够保证可见性 。
(3) 可以通过volatile关键字来保证一定的“有序性”(具体原理在下一节讲述)。另外可以通过synchronized和Lock来保证有序性,很显然,synchronized和Lock保证每个时刻是有一个线程执行同步代码,相当于是让线程顺序执行同步代码,自然就保证了有序性。
java中有析构函数,但我们一般用不到它,因为java有自动内存回收机制,无需程序员来释放,也就不要担心内存泄露,只不过java中析构函数所采用的方式不是C++中的那样前加~号,在java中 对象析构时会调用void finalize()方法,因此你如果确实需要析构的话就可以为你写的类添加一个void finalize(){}方法,来完成你所需要的工作。
在Object类中的源代码:protected void finalize() throws Throwable{ }
GC负责调用finalize()方法。
finalize()方法只有一个方法体,里面没有代码,而且这个方法是protected修饰的。
这个方法不需要程序员手动调用。JVM的垃圾回收期负责调用这个方法。
finalize()只需要重写,重写完将来自动有人来调用。
finalize()方法的执行时期:
当一个java对象即将被垃圾回收器回收的时候,垃圾回收器负责调用finalize()方法。
finalize()方法实际上市SUN公司为java程序员准备的一个时机,垃圾销毁时机。
如果希望在对象销毁时机执行一段代码的话,这段代码要写在finalize()方法当中。
1、不管有没有出现异常,finally块中代码都会执行;
2、当try和catch中有return时,finally仍然会执行;
3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;
4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。
线程不安全的懒汉式:
public class Singleton {
private static final Singleton instance;
private Singleton () {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
双重锁检测:
//正确的双重检测锁
public class Singleton {
private volatile static final Singleton instance;
private Singleton () {}
public static Singleton getInstance() {
if (instance == null) { //第一次空检测
synchronized (Singleton.class) {
if (instance == null) { //第二次空检测
instance = new Singleton(); //实例化对象
}
}
}
return instance;
}
}
线程安全的懒汉式:
public class Singleton {
private static final Singleton instance;
private Singleton () {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
饿汉式:
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton () {}
public static Singleton getInstance() {
return instance;
}
}
静态内部类实现:
public class Singleton {
private Singleton () {}
public static Singleton getInstance() {
return SingletonInner.instance;
}
private static class SingletonInner {
private static final Singleton instance = new Singleton();
}
}
枚举类实现
public enum Singleton {
INSTANCE;
}
因为我在自己的技术栈里面写了了解C++,我是在上学的时候用C++,而且用的都是OpenCV相关的库,所以属于是给自己挖坑了
根据树的前序、中序遍历结果重构二叉树(剑指offer07)
面了两个部门,第一个部门面完了HR反馈面的还不错,但是经历跟部门不太匹配。所以又换了个部门,但是还是挂了
(1)Java基础
volitale关键字
synchronized关键字
JVM垃圾回收
栈、堆
JVM哪些数据存在堆
JVM哪些数据存在栈
分布式锁怎么用
(2)项目相关
MySQL
隔离级别
索引用什么存储
B+树结构、特点
查询一个id > 100 and id < 200,查询的过程
索引相关
(3)算法题
Excel的列的转换,类似于A是第一列,B是第二列,AA是第27列,以此类推(LeetCode168)
(4)反问
一面忘记了
(1)项目
(2)技术基础:
JVM的内存分区、垃圾回收机制
CMS算法什么时候会发生stop the world
g1算法为什么这么快
mysql的事务隔离级别
mysql为什么不用哈希表,为什么不用二叉树
mq如何避免消息丢失
Redis的主从复制
synchronized 和 ReentrantLock的区别
Redis的持久化方法
(3)算法题:
一个二维矩阵,每行从左到右递增,每列从上到下递增,找出其中是否存在某个数(特别经典的题,剑指offer和LeetCode都有)
(4)反问:
华为社招的正编岗位非常非常少,而且流程巨慢。我这个一直到我入职都没有等来面试。但是也有一起找工作的同学,一年经验社招进了华为正编。
面试之前要先参加笔试,参加之前建议在牛客网练习一下,因为华为的机考要自己处理输入输出
笔试题:
(1)两个字符串数组,去重并排序
(2)某个瑕疵度(以元音字母开头和结尾、字符串中的辅音的个数叫做瑕疵度)的最长子字符串。
1)、写算法题
判断一棵树是否是二叉搜索树(LeetCode98)
2)、项目
3)、系统设计
如何获取关注和粉丝列表
24小时热帖
延迟队列(比如下单15分钟之后看一下有没有结算)
(1)项目:项目亮点(需要提前想好怎么说),针对性的问了一些问题
(2)技术基础
数据库
如何优化慢sql 回答建立索引
索引什么条件下会失效
数据库连接池的作用
数据库的事务,如何保证事务 加锁
数据库的索引是用什么结构存储的 B+树的时间复杂度是多少,为什么是这样
多线程
wait()和sleep()
Java基础
ArrayList LinkedList HashMap HashSet之间的区别和联系
了解几种排序,时间复杂度分别是多少
其他
一致性哈希
(3)算法题
删除链表中的倒数第n个节点,前面提过的
(1)项目
(2)写算法题:
两个整数做除法,如果结果是循环小数,用()把循环的部分括起来。
技术问题忘了,把记得的算法题写一下
二面:荷兰国旗问题
三面:LRU缓存