拿到 阿里实习offer,经历了5次面试,其中4轮技术面,1轮HR面试。在这里分享一下自己的面试经验和学习总结。希望能够帮助更多的小伙伴。
我本科毕业于中南大学信管专业,真正开始学习Java是在大三下学期,研究生就读北航的移动云计算专业。刚开始也是小白,也是一步步成成起来的。需要提的一点是,你将来是需要靠这个吃饭的,所以请对找工作保持十二分的热情,而且越早准备越好。
一面是在上午9点多接到支付宝的面试电话的,因为很期望能够尽快接到阿里的电话,所以非常兴奋。电话接通之后还是非常紧张的,毕竟是第一次这样的面试。
1.synchronized与Lock的区别
synchronized<--->Lock
参考:京东18届一年半经验社招.md#synchronized和lock的区别必考
2.synchronized与Lock的使用场景
一般情况下两个都可以使用,这时候推荐使用synchronized,原因是虚拟机在未来的性能改进中会更偏向于原生的synchronized,但是在特殊场景下需要考虑使用Lock:
3.synchronized源码的了解
推荐阅读:
深入分析Synchronized原理(阿里面试题)
「阿里面试系列」分析Synchronized原理,让面试官仰望
1.JVM自动内存管理
①哪些内存需要回收?
不可能再被任何途径使用的对象需要被回收。
②怎么判断内存是够能够回收?
由于引用计数法很难解决对象循环引用的场景,因此一般都使用可达性分析来判断一个对象是否存活。
③什么时候回收?
新生代的回收时机
新的对象需要在Eden区申请内存,但Eden区没有足够的连续的空间分配给对象会触发一次minor GC
老年代的回收时机
从新生代过来的对象需要在老年代申请空间,但老年代没有足够的连续的空间来分配,会触发一次major GC。
HotSpot VM 老年代给新生代做空间担保时,若老年代连续可用空间小于历次晋升到老年代对象的平均大小,触发一次major GC。
④如何回收?
回收算法
垃圾回收器
推荐阅读:
JVM自动内存管理机制
2.Minor GC与Full GC的触发机制
参考京东18届一年半经验社招.md#minor-gc和full-gc触发条件
第一步:JVM性能定义
第二步:JVM性能调优原则
MinorGC回收原则: 每次minor GC 都要尽可能多的收集垃圾对象。以减少应用程序发生Full GC的频率。
GC内存最大化原则:处理吞吐量和延迟问题时候,垃圾处理器能使用的内存越大,垃圾收集的效果越好,应用程序也会越来越流畅。
GC调优3选2原则: 在性能属性里面,吞吐量、延迟、内存占用,我们只能选择其中两个进行调优,不可三者兼得。
第三步:进行调优
内存占用调优
延迟调优
吞吐量调优
推荐阅读:
如何合理的规划一次jvm性能调优
JVM 调优方法
推荐阅读:
京东评价系统海量数据存储设计
①确认是否需要缓存
②本地缓存选择
③分布式缓存
④多级缓存
⑤缓存更新
⑥缓存问题
⑦缓存监控
推荐阅读:
如何优雅的设计和使用缓存?
设计缓存架构时的一些注意事项
一般来说,热门商品信息存放在分布式缓存中,在JVM中一般存放在堆中。
把内存中的物理地址空间和程序中的逻辑地址空间各分成若干个大小相等的块,逻辑空间中的块称为页面,物理空间中的块称为物理块。
页式存储管理的优点是将作业的连续逻辑地址空间划分成页,可以分配到内存中不连续的块中,也就是分配到内存的不连续的主存区域中,并且能使作业正确的执行,这样进一步的提高了主存空间的利用率。缺点是当处理器处理一个作业时,必须访问两次主存,第一次是访问页表从而找到页号所对应的块号,然后换算出作业的绝对地址,第二次是处理器再按照换算出程序在主存中的绝地地址再进行运算操作。
推荐阅读
操作系统的页式存储
被volatile
关键字修饰的变量,在每个写操作之后,都会加入一条store
内存屏障命令,此命令强制工作内存将此变量的最新值保存至主内存;在每个读操作之前,都会加入一条load
内存屏障命令,此命令强制工作内存从主内存中加载此变量的最新值至工作内存。
①happens-before含义:前面一个操作的结果对后续操作是可见的。
如果一个操作happens-before另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前。
两个操作之间存在happens-before关系,并不意味着一定要按照happens-before原则制定的顺序来执行。如果重排序之后的执行结果与按照happens-before关系来执行的结果一致,那么这种重排序并不非法。
②happens-before原则
程序的顺序性规则:在一个线程中,按照程序顺序,前面的操作 Happens-Before 于后续的任意操作。
管程中锁的规则:这条规则是指对一个锁的解锁 Happens-Before 于后续对这个锁的加锁。
volatile变量规则:对一个volatile变量的写操作happen—before后面(时间上)对该变量的读操作。
线程启动 start() 规则:它是指主线程 A 启动子线程 B 后,子线程 B 能够看到主线程在启动子线程 B 前的操作。
线程终止 join() 规则:这条是关于线程等待的。它是指主线程 A 等待子线程 B 完成(主线程 A 通过调用子线程 B 的 join() 方法实现),当子线程 B 完成后(主线程 A 中 join() 方法返回),主线程能够看到子线程的操作。当然所谓的“看到”,指的是对共享变量的操作。
线程中断interrupt()规则:对线程interrupt()的调用 happen—before 发生于被中断线程的代码检测到中断时事件的发生。
对象终结finalize()规则:一个对象的初始化完成(构造函数执行结束)happen—before它的finalize()方法的开始。
传递性规则:如果操作A happen—before操作B,操作B happen—before操作C,那么可以得出A happen—before操作C。
推荐阅读:
【并发重要原则】happens-before理解和应用
推荐阅读:
lucene 全文检索原理和流程
评价一下我的这次面试表现
应该在我的技术栈中增加什么
有机会下次面试吗
一面总结
一面大概面了50多分钟,从面试官口中得知他是一个老员工,比我大不了多少,总体上还是聊得蛮投机的。最后的三个问题是我问面试官的,在回答我是否还有机会下次面试的时候说:竞争很激烈,不过机会还是有的。
可以看出一面的问题不是很难,但是要得到面试官比较高的评价,还是需要一定的表达能力和对技术比较本质的认识的,如果在回答问题的时候能够做一些适当的扩展,自然会让面试官对你有不一样的评价。
我回答问题的遵循一定的步骤:先回答问题本质,在回答具体细节,最后做一些平时编程中的扩展。这样,会让面试官觉得你确实是在这个技术上面下过功夫的。
等了将近6天(还以为被刷了呢)终于在第二周的周四接到阿里面试电话,那叫一个激动啊。赶紧找了一个安静的地方,准备好后开始正式面试。二面的面试官是一个部门主管,自然还是有点小紧张的。这次面试官上来就直接问,没有一面的面试官那么好说话。
乐观锁/悲观锁
独享锁/共享锁(具体实现互斥锁/读写锁)
可重入锁:可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。ReetrantLock/Synchronized均为可重入锁。
公平锁/非公平锁
分段锁:是一种锁的设计,并不是具体的一种锁,对于ConcurrentHashMap而言,其并发的实现就是通过分段锁的形式来实现高效的并发操作。
偏向锁/轻量级锁/重量级锁
自旋锁:在Java中,自旋锁是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU。
推荐阅读:
Java中的锁分类与使用
参考:volatile关键字的如何保证内存可见性
①浏览器根据域名解析IP地址;
②浏览器与WEB服务器建立一个TCP连接
③浏览器给WEB服务器发送一个HTTP请求
④服务器端响应HTTP请求,浏览器得到HTML代码
⑤浏览器解析HTML代码,并请求HTML代码中的资源
⑥关闭TCP连接,浏览器对页面进行渲染呈现给用户
推荐阅读:
HTTP请求的完全过程
TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。
参考:京东18届一年半经验社招.md#为什么不能两次握手
AOP的思想是,不去动原来的代码,而是基于原来代码产生代理对象,通过代理的方法,去包装原来的方法,就完成了对以前方法的增强。换句话说,AOP的底层原理就是动态代理的实现。
参考:Spring的IOC/AOP的实现(必考)
参考:
动态代理的实现方式(必考)
pring AOP实现有哪几种实现,接口代理和类代理会有什么区别?
Ioc容器的加载过程实际上问的是Spring的生命周期。
参考:java后端社招面试经历(三年工作经验).md#spring生命周期
主要过程:词法解析--->语法解析--->语义解析--->生成字节码
①词法解析:javac编译器执行字节码编译的第一步。主要任务就是将java源码中的关键字和标示符等内容转换为符合java语法规范的Token序列,然后按照指定的顺序规则进行匹配校验,以便为后续的语法解析步骤做准备。
②语法解析:将匹配后的Token序列整合为一颗结构化的抽象语法树。也就是说,词法解析后的Token序列其实还并不完善,因为这些Token所代表的只是一个对应的单个源码字符集合,还并没有按照指定的语法规则将其相关的一组或者一段Token整合起来。
③语义解析:为没有构造方法的类型添加缺省的无参构造方法/检查任何类型的变量在使用前是否都已经经历过初始化/检查变量类型是否与值匹配...
④生成字节码:是将符合Java语法规范的java代码转换为符合JVM规范的字节码文件。
推荐阅读:
字节码的编译原理
二面总结
二面面试官问的问题都比较直接,答案也是知道就知道,不知道就不知道。这些问题一部分是基础,一部分是根据你的专业技能的来提问的。
面完后面试官对我的评价是:中规中矩,有机会下次面试。虽说是中规中矩,但听到面试官说有机会下次面试就感觉这次面试应该过了。
虽说这次面试过了,但是我在思考的是为什么面试官对我的表现是中规中矩。后面我知道我的回答虽然答到了点子上,但是扩展程度不够,对一些问题的理解缺乏足够的实践经验。面试官告诉我,有时间可以去研究字节码的编译过程,以及JVM调优方面的知识(特别强调这个很重要)。
针对自己的不足,面完后又投入疯狂的看书写代码的生活中。虽然在面试中有一些回答不出来很正常,但是如果能够做到出乎面试官的意料,也是面试官对你很重要的加分项。
三面与二面隔了5天,找了一个安静的地方开始电话面试。据说总监面会问项目多一点,所以在等待的这几天中给项目增加了几个比较肉的点。总监刚上来非常不客气,最尴尬的是总监那边老感觉有回声,因为不好意思提就忍了。
自由发挥,略
自由发挥,略
自由发挥,略
自由发挥,略
自由发挥,略
自由发挥,略
存放于数据库。
方式:session和COOKIE两种方式
区别:
推荐阅读:
session和COOKIE的区别
1.直接将信息存储在COOKIE中
2.tomcat集群,tomcat之间进行session复制
3.Nginx进行ip-hash
4.Redis进行存储session
推荐阅读:
4种分布式session解决方案
管理分布式session的四种方式
public static int getIndex(int[] a,int x) {
int start = 0;
int end = a.length-1;
while (start<=end) {
int middle = (end+start)/2;
if(x==a[middle])
return middle;
else if (x end = middle -1;
}else {
start = middle +1;
}
}
return -1;
}
public class Sort_quick_sort {
public void quick(int[] src, int begin, int end) {
if (begin
int key = src[begin];
int i = begin;
int j = end;
while (i
while(i
j--;
}
//上面循环结束,说明右边不大于基准数了,换位置
if (i
i++;
}
//如果左边的小于基准,i++
while (i
}
//上面循环结束,说明左边不小于基准数了,换位置
if (i
j--;
}
}
//当i== j的时候,基准数停留在了它应该在的位置,分而治之的递归下去
quick(src, begin, i - 1);
quick(src, i + 1, end);
}
}
public void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String args[]) {
Sort_quick_sort obj = new Sort_quick_sort();
int[] num = {2, 7, 11, 15, 1, 0, 0,15};
obj.quick(num, 0, num.length - 1);
for (int n: num){
System.out.print(n+ "\n");
}
}
}
推荐阅读:
快排-无序整数数组中找第k大的数(或者最小的k个数)
JDK源码中用到的设计模式
三面总结:
本以为三面是交叉面,没想到是阿里的总监面试。由于具体的技术问题在前两轮面试中已经问过了,所以三面后不会有具体的技术问题,总结来看,对自己做过的项目一定要深入,包括使用使用到的技术原理、为什么要使用这些技术。
针对项目,面试官关注的无非以下几点:
对于写在简历上面的项目,自己对照上面四个问题进行思考,才会在面试中游刃有余。因为任何在简历中作假的行为,面试官只要详细问你就露馅了。在听到面试官说有机会下次面试的时候,心中自然是非常高兴的。
果然,在第二天下午四点多接到了部门总监的电话,简单沟通后开始了面试。这次面试感觉是最放松的,没有什么高深的技术问题,感觉就像和朋友聊天的感觉,真的很感谢这位面试官。
下面是面试中的问到的问题:
四面总结:
虽然这面比较轻松,也没有什么具体的技术问题,但对项目仍然是面试官关注的,后面了解到总监面除了看你的基础,主要看你的潜力(就是有没有培养的价值),这个东西看起来挺虚的,但是从你平时的学习中仍然是可以看得出来的。所以,作为一名开发人员,平时对技术的研究也是很重要的。在听到面试官说让我好好等HR通知的时候可开心了,感觉饭都吃得更香了。
在隔了4天左右,终于接到了HR的电话,那叫一个激动啊。感觉离阿里offer已经不远了,于是振奋精神,聊得还不错。
下面是HR问我的问题:
关于HR面试:
其实早就听说HR面试的最终的录取结果具有一票否决权,在面完前面的技术面试之后,还是很担心的。所以咨询了师兄以及网上找了阿里HR面试的资料,大概得到以下结论:
关于面试的心态:
在自己拿到阿里offer之前,一直都在想一个问题:我到底该如何做才能离阿里更近?一年的成长与思考让我认清了这点,虽然中间也遇到过很多坑,但却真正让我对自己有了一个清晰的定位,也有了比较明确的目标。正因为如此,我每天所学习的都给我莫大的动力,让我不断进步,并最终实现自己的目标。所以迷茫才是最可怕的,只有摆正心态,对找工作保持十二分的热情,勤奋努力,才能离目标更近一步。
但是有了目标和努力外,不一定就能实现目标,说到底还有一个运气的成分在里面,只能说你找到心仪的工作概率更大而已。遇到一个好的面试官绝对赚了。这四位阿里的面试官我感觉都挺好的,没有因为他们资历深就为难我,所以还是非常感谢这四位技术面试官的。
一点总结
由于本科是非科班出身,也仅仅是接触过Java而已,在大三的时候对自己的未来的发展道路很迷茫,不知道何去何从,感觉自己就是一个loser。那会考完研后有幸进入了金蝶实习,也就是那段时间让我认清了自己的短板,自己欠缺的是什么,那段时间也是我确立自己目标的过程。读研后疯狂看书、写代码、写博客、做项目,每天都在对自己进行总结和反思,正是这样一个不断的自我反思与努力的过程中,我得到了真正的成长与进步。也是这段经历让我能够面对阿里技术面试官的提问应答自如,从而顺利拿到阿里的offer。
最后,想送给自己两句话以鞭策自己
越努力,越幸运!以现在大多数人的努力程度之低,根本轮不到可以拼天赋。