更新。刚刚收到 offer
—————————————————————–
emmmm面试结果还不知道,分享下面经积攒一下人品,有些问题可能记不清或者忘了。
一面
jvm 的局部变量表是做什么的?存储局部变量、函数调用时传递参数,很多字节码指令都是对局部变量表和操作数栈进行操作的。
双亲委派有了解吗?类加载器加载类时先委派给父类加载,只有父类无法加载时,自己才尝试加载。
为什么要双亲委派?保证java类库中的类不受用户类影响,防止用户自定义一个类库中的同名类,引起问题。
垃圾回收怎么判断哪些对象应该回收?可达性分析,从 GCRoot 开始遍历,不能遍历到的对象就可以认为已经死了,可以回收。
什么可以作为GCRoot?方法区的数据引用、当前代码处的局部变量,基本就是用户能通过代码引用到的。
Redis 是了解是吧?了解到什么程度?emmmm会用吧。
(面试官内心:那算了)
Mysql 比较熟悉是吧?说一下底层数据存储原理?如果直接线性存储的话,每次查找数据都要整个遍历一遍,那么复杂度就是log(n),于是可以用二叉树来存储,把复杂度降低到约log(n),但是二叉树有个特点就是,它有可能因为插入顺序的问题,变得不平衡,最坏情况就是都在节点一边,又变成了log(n),所有就通过改进插入和删除等操作,保证每次操作完后树都是平衡的,就有了B树……
B树怎么保证每次操作完都平衡的?不知道。正准备拿红黑树来讲,面试官补充了一下,讲 mysql 里的B树,我只记得应该是用的B+树,但是还没看B+的数据结构,干脆说不了解,面试后查了一下,跟红黑树还是差不太多的……
说一下建表时,建索引有哪些要注意的。选区分度比较大的,选数据类型比较小的比如整数而不要选长字符串,选where子句中出现的,覆盖索引 balabala……
写代码:实现一个 hashtable。我首先说了下思路,然后先写了个简单的,碰撞冲突采用的拉链法,注意一下边界条件的处理,null什么的。
如果元素变多会怎样?碰撞冲突会增多,链表会边长,效率变低。
怎么解决?达到一定数量的时候,对数组扩容,然后把所有元素重新hash一遍。
保证线程安全怎么做?最简单的直接方法上加synchronized关键字。
这样效率比较低,怎么解决?分段锁。
一面结束后很快就是二面,原来是连续面试的……
二面
线程池了解吗?为什么要线程池?节省线程创建销毁的开销balabala……
线程池的中的线程数量能不能无限增加,为什么?不能,线程需要一定开销,太多线程会耗尽计算机资源,(而且过多线程也无法发挥多线程的优势,毕竟cpu核就那么多)
java 里任务提交给线程池后,那些任务是存储在哪的?这里一开始没懂面试官的意思,面试官给了两次提醒,想起是把任务用 Runable(其实也可以是Callable) 表示,放在一个阻塞队列里。
阻塞队列怎么实现?创建一个数组或者链表,每次取元素或者放元素就对数组操作。没有元素而要取元素时,阻塞,满了而要放元素时,阻塞。
队列满了,那个线程池的 submit 方法会阻塞在那里?emmm应该不会,那应该是动态扩容……
数组怎么扩容?新建一个更大新数组,然后复制过去……
复制的时候锁住数组,所有的操作都阻塞?emmmmm答不出来了
(面试官心里:编,继续编)
(面试之后去看了线程池里的阻塞队列,似乎都是用链表实现的,没有用数组。用到的队列似乎默认都是动态扩容的,最大为整数最大值。如果队列满了又不支持动态扩容,可以通过设置饱和策略来处理,默认是中止,也就是抛出 RejectedExecutionException。)
讲一下 volatile 。内存可见性、指令重排、32位jvm对64数据的原子操作什么的
volatile 可以保证并发计数正确性?不能
如果需要保证并发计数正确怎么办,只能加锁吗?一开始说用一个队列来存放增加操作,只用一个线程来更新,面试官说计数本来是个轻量级的操作,你还用一个队列……(当场去世)还好及时想起 java 有原子变量,于是说 AtomicInteger。
为什么原子变量能保证高效正确计数?因为是底层提高了支持,一不小心说用了CAS算法……
说下 CAS 算法?比较给定值与某变量当前值,若相同,设置变量为第三个值,否则什么都不做,一直这么操作,直到成功。然后一不小心说如果一个数据A变成B,又变回A,还是成功……
如果系统不能容忍 ABA 问题怎么解决 CAS 的 ABA 问题?忘记了,人生中最痛苦的事莫过于,记得高并发那本书有讲到,却忘了讲的什么(用一个 version 变量记录版本,或者 java 提供的 AtomicStampedReference)
说下 mysql 的读写分离。
读写分离有什么用?写操作都在主库,读操作都在分库,让读操作能并发,提高效率。
如果有多个变量要更新,要保证一致性,怎样加锁来保证正确性,效率又比较高?只在写时加锁,读不加锁……
那怎么解决一个写操作修改了部分变量,读操作,读取了这个中间状态的问题?emmm写操作时,先锁住锁1,在线程本地也就是函数局部计算完所有结果后,锁住锁2,一次更新完后再释放2个锁,读操作只锁住锁2……
说下 TCP 连接四次挥手。
为什么要有 time_wait 。忘了(其实不久前才看了一次,防止影响新连接,主动关闭方如果直接退出了,收到被动关闭方的重发 fin 时,只能返回 RST 而不能返回 ACK)
写代码:一个二叉树,每个节点除了有左右子节点外,还有指向父节点的引用。给出一个节点,返回它在二叉树中中序遍历的下一个节点。
三面
选个自己觉得收获最大的项目讲一讲。
然后问了一些项目有关的问题
SpringMVC 处理请求的整个流程?入口?不知道,流程强行答了一遍,入口不知道……
Servlet 的生命周期?(init、service、doGet、doPost、destroy什么的)
Servlet 3.0 新特性?只知道一个注解(注解、异步、还有个插件还是什么的)
详细讲下 TCP 连接四次挥手。
这次面试相对比较短,大概讲项目的时间有点长,问的问题也相对较少……
四面
(这位面试官应该是个 HR 吧。。)
首先还是问项目,也问了些项目有关的偏技术的问题
平时学习技术的方法,最近在看什么书……
觉得怎样提高解决问题的能力……
记得的大概就这么多……等结果了。。。