你知道的越多,你不知道的越多点赞再看,养成习惯java
本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试点思惟导图,也整理了不少个人文档,欢迎Star和完善,你们面试能够参照考点复习,但愿咱们一块儿有点东西。mysql
还记得我上周说的重庆邮电研二的读者么?git
、github
知道他拿了Offer以后我也很开心,我就想把它的面试经历和面试题分享出来,这样让你们也知道,目前实习的面试大概是怎么样子的。面试
很优秀的是,他每次面试都会本身作总结,我一说他就直接给到了我文档,优秀的仔,我可能知道他拿这么多Offer的缘由了吧。算法
整个文章我原本想贴一下面试过程,而后贴下面试题就完事了,这就能够水一篇了。sql
可是大家确定会骂我是渣男,不负责任,题目都给了还不给我答案。数据库
我暖男来的,最后仍是给大家写了答案,别爱我,没结果。编程
这是一个秋高气爽的早上,Angela丙丙一如既往的睡着懒觉,呼、呼、呼的呼噜声忽弱忽强。设计模式
叮叮叮,⏰闹钟响了,Angela丙丙如往常般,闭着眼睛摸到了手机并关了,正准备呼呼大睡。
忽然一个激灵,Angela丙丙想到了什么,“今天还有百度和京东的面试,卧*差点睡过头”。
一眨眼的功夫,Angela丙丙已经坐在了,京东和百度一面的会议室了。(我整合了两个公司一面的问题,作了去重)
门开了,一个大腹便便,穿着格子衬衣的中年男子,拿着一个尽是划痕的mac向你走来,看着快秃顶的头发,心想着确定是尼玛顶级架构师吧!
是否是很熟悉,是我第一篇文章的面试官
小伙子自我介绍下,顺便把你作过的项目介绍一下。
面试官您好我叫Angela丙丙今年23岁,我来自贵州遵义,毕业于蓝翔技工职业学校电子信息工程专业,今年已经工做两年了,以前有过华为的实习经历,主要在nova团队负责核心组件开发,和团队小伙伴攻坚难题。
如今的公司是天猫国际,主要负责活动小组的研发,担任小组的小组长,在公司一年期间,参加过大大小小活动30多场,活动为公司带来9次过千万的GMV的活动,负责的项目主要是使用了微服务的设计思想和分布式的部署方式。
常常用到的中间件有Redis,RocketMq,ElasticSearch,Logstash,Canal,、Dubbo等等,对Dubbo的源码有着深刻的研究和看法,而且仿照Dubbo用Netty也写了一个类Rpc框架,如今已经开源到了GitHub,而且有了2万的Star。
而且会用业余时间撰写技术博客,在各大博客论坛都要 必定的粉丝量。
我对电商全部的业务流程都有一些了解,对线上问题处理以及性能调优都有本身的理解,对业务的研发设计流程也十分熟悉。
由于我的缘由选择了离职,若是能有幸加入贵公司一块儿共事,我想我能第一时间上手并产出结果,以上就是个人自我介绍,谢谢面试官。
Tip:以上自我介绍所有内容都是虚构的,只是给你们一个面试自我介绍的Demo,面试题就是Angela小丙的面试题了。
Angela丙丙?简历上看到你作过项目组长,你在作组长以后作了那些工做,说一下你学到了那些东西。
帅气的面试官您好,进入公司以后,我由于项目调动成为了小组的Leader,这并无我想的爽,由于以前就是负责本身份内的事情就行了,如今须要有项目的大局观,还有项目进度把控,已经组员的代码和方案的Review。
小组同窗都很是优秀,我若是要Hold住他们,就得逼迫本身去不断的学习,因此这段时光很是痛苦,可是获得的收获倒是实实在在的。
有看过HashMap源码吗?
嗯嗯这个我看过的,由于实际开发过程当中,Map仍是比较常见的面试题。
JDK1.7中HashMap的put()方法全过程。JDK1.8有那些变化。
JDK1.7当中HashMap中线程不安全问题有那些?缘由分别是什么?
JDK1.8以后如何链地址法,链表长度是多少的时候会转换成红黑树。
节点个数是多少的时候,红黑树会退回链表。
为何会选择8做为链表转红黑树的阈值。
根据泊松分布,在负载因子默认为0.75的时候,单个hash槽内元素个数为8的几率小于百万分之一,因此将7做为一个分水岭,等于7的时候不转换,大于等于8的时候才进行转换,小于等于6的时候就化为链表。
HashMap与HashTable有什么区别?有没有了解过ConcurrentHashMap?
JDK1.8以后ConcurrentHashMap如何保证线程安全性?(CAS+synchronized),这里还顺便问了synchronized和可重入锁的区别。
与JDK1.7相比有那些优化?
关于HashMap和ConcurrentHashMap的知识点我写过了,就不作重复工做了,去看看我HashMap和ConcurrentHashMap相关的文章就行了(跟我介绍的内容基本一致,以我为准):
说到synchronized,说些synchronized加载static关键字前和普通方法前的区别?
Synchronized修饰非静态方法,其实是对调用该方法的对象加锁,俗称“对象锁”
Synchronized修饰静态方法,其实是对该类对象加锁,俗称“类锁”。
看你熟悉单例,介绍下单例模式而且说下单例懒汉式和饿汉式的区别?(手写)
单例的介绍:
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决:一个全局使用的类频繁地建立与销毁。
什么时候使用:当您想控制实例数目,节省系统资源的时候。
如何解决:判断系统是否已经有这个单例,若是有则返回,若是没有则建立。
关键代码:构造函数是私有的。
应用实例:
优势:
缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
使用场景:
注意事项:getInstance() 方法中须要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入形成 instance 被屡次实例化。
懒汉
public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
饿汉
public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; } }
懒汉式下如何保证线程安全?
public class Singleton { private static Singleton instance; private Singleton (){} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
建立线程安全的单例有那些实现方法?
双检锁/双重校验锁(DCL,即 double-checked locking)
public class Singleton { private volatile static Singleton singleton; private Singleton (){} public static Singleton getSingleton() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
登记式/静态内部类
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
枚举
public enum Singleton { INSTANCE; public void whateverMethod() { } }
说一下JVM的内存模型?(每个模块都说)
方法区(Method Area)
方法区主要是放一下相似类定义、常量、编译后的代码、静态变量等,在JDK1.7中,HotSpot VM的实现就是将其放在永久代中,这样的好处就是能够直接使用堆中的GC算法来进行管理,但坏处就是常常会出现内存溢出,即PermGen Space异常,因此在JDK1.8中,HotSpot VM取消了永久代,用元空间取而代之,元空间直接使用本地内存,理论上电脑有多少内存它就可使用多少内存,因此不会再出现PermGen Space异常。
堆(Heap)
几乎全部对象、数组等都是在此分配内存的,在JVM内存中占的比例也是极大的,也是GC垃圾回收的主要阵地,平时咱们说的什么新生代、老年代、永久代也是指的这片区域,至于为何要进行分代后面会解释。
虚拟机栈(Java Stack)
当JVM在执行方法时,会在此区域中建立一个栈帧来存放方法的各类信息,好比返回值,局部变量表和各类对象引用等,方法开始执行前就先建立栈帧入栈,执行完后就出栈。
本地方法栈(Native Method Stack)
和虚拟机栈相似,不过区别是专门提供给Native方法用的。
程序计数器(Program Counter Register)
占用很小的一片区域,咱们知道JVM执行代码是一行一行执行字节码,因此须要一个计数器来记录当前执行的行数。
熟不熟悉垃圾回收算法?给我介绍一下垃圾回收算法有哪些?
标记清除
标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。
在标记阶段首先经过根节点(GC Roots),标记全部从根节点开始的对象,未被标记的对象就是未被引用的垃圾对象。而后,在清除阶段,清除全部未被标记的对象。
复制算法
从根集合节点进行扫描,标记出全部的存活对象,并将这些存活的对象复制到一起新的内存(图中下边的那一起内存)上去,以后将原来的那一起内存(图中上边的那一起内存)所有回收掉
标记整理
复制算法的高效性是创建在存活对象少、垃圾对象多的前提下的。
这种状况在新生代常常发生,可是在老年代更常见的状况是大部分对象都是存活对象。若是依然使用复制算法,因为存活的对象较多,复制的成本也将很高。
分代收集算法
分代收集算法就是目前虚拟机使用的回收算法,它解决了标记整理不适用于老年代的问题,将内存分为各个年代。通常状况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),在堆区以外还有一个代就是永久代(Permanet Generation)。
在不一样年代使用不一样的算法,从而使用最合适的算法,新生代存活率低,可使用复制算法。而老年代对象存活率搞,没有额外空间对它进行分配担保,因此只能使用标记清除或者标记整理算法。
如何断定一个对象是否应该回收。
为了解决循环引用的问题,java中采起了正向可达的方式,主要是经过Roots
对象做为起点进行搜索,搜索走过的路径称为“引用链”,当一个对象到 Roots
没有任何的引用链相连时时,证实此对象不可用,固然被断定为不可达的对象不必定就会成为可回收对象。
被断定为不可达的对象要成为可回收对象必须至少经历两次标记过程,若是在这两次标记过程当中仍然没有逃脱成为可回收对象的可能性,则基本上就真的成为可回收对象了,可否被回收其实主要仍是要看finalize()
方法有没有与引用链上的对象关联,若是在finalize()
方法中有关联则自救成功,改对象不可被回收,反之若是没有关联则成功被二次标记成功,就能够称为要被回收的垃圾了。
除了垃圾回收,还有那些工做会形成CPU负载太高(其实这里给出的是一个场景,就是让描述一下除了垃圾回收以外,还有那些工做会让线上CPU占用到百分之90-100,而且给出排查过程。)。说一下CMS垃圾回收器和G1收集器的特色,和收集过程。
CMS收集器是一种以获取最短回收停顿时间为目标的收集器。基于“标记-清除”算法实现,它的运做过程以下:
初始标记、重新标记这两个步骤仍然须要“stop the world”,初始标记仅仅只是标记一下GC Roots能直接关联到的对象,熟读很快,并发标记阶段就是进行GC Roots Tracing,而从新标记阶段则是为了修正并发标记期间因用户程序继续运做而致使标记产生表动的那一部分对象的标记记录,这个阶段的停顿时间通常会比初始标记阶段稍长点,但远比并发标记的时间短。
CMS是一款优秀的收集器,主要优势:并发收集、低停顿。
缺点:
浮动垃圾:因为CMS并发清理阶段用户线程还在运行着,伴随着程序运行天然就会有新的垃圾不断产生,这部分垃圾出现的标记过程以后,CMS没法在当次收集中处理掉它们,只好留待下一次GC中再清理。这些垃圾就是“浮动垃圾”。
G1是一款面向服务端应用的垃圾收集器。G1具有以下特色:
一、初始标记;二、并发标记;三、最终标记;四、筛选回收
String a = “abc” ; 和String b = new String(“abc”) ; 是否是同样的?为何? 他们对应的内存空间分别是什么?
不同
常量池
指的是在编译期肯定,并被保存在已编译的字节码文件中的一些数据,它包括类、方法、接口等中的常量,存放字符串常量和基本类型常量(public static final)。
栈(stack)
主要保存基本数据类型(或者叫内置类型)(char、byte、short、int、long、float、double、boolean)和对象的引用,数据能够共享,速度仅次于寄存器(register),快于堆。
因此他们在 == 的时候是false
说一下JVM建立对象的过程。
常量池中定位类的符号引用
↓
检查符号引用所表明的类是否已被加载,解析和初始化过 →
↓ ↓
分配内存(类加载完成后,内存需求肯定) ← 加载
↓
根据java堆是否规整(GC方法)选择分配方法
↙ ↘
指针碰撞 空闲列表
↓
分配内存的并发保证(指针更新的原子性)
↙ ↘
CAS+失败重试 按照线程划分在不一样的空间中进行TLAB -XX:+UseTLAB -XX:-UseTLAB
↓
内存空间初始化为0值,保证对象的实例字段能够不赋初值就可使用。
↓
设置对象头信息(Object Header):引用指针,元数据,hash值,GC分代年龄,锁相关
↓
执行对象方法
说一下byte a = 127, byte b = 127; a+=b 和a = a+b的区别分别会出现什么问题。
a+=b 会出现负数。
a=a+b 会直接报错。
强制类型提高形成的
是否熟悉mysql? 说一下mysql的隔离级别和对应的问题。
Read Uncommitted(读取未提交内容)
在该隔离级别,全部事务均可以看到其余未提交事务的执行结果。本隔离级别不多用于实际应用,由于它的性能也不比其余级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
Read Committed(读取提交内容)
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它知足了隔离的简单定义:一个事务只能看见已经提交事务所作的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),由于同一事务的其余实例在该实例处理其间可能会有新的commit,因此同一select可能返回不一样结果。
Repeatable Read(可重读)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到一样的数据行。不过理论上,这会致使另外一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另外一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎经过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
Serializable(可串行化)
这是最高的隔离级别,它经过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每一个读的数据行上加上共享锁。在这个级别,可能致使大量的超时现象和锁竞争。这四种隔离级别采起不一样的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:
什么是MVCC,主要是为了作什么?
MVCC(Mutil-Version Concurrency Control),就是多版本并发控制。MVCC 是一种并发控制的方法,通常在数据库管理系统中,实现对数据库的并发访问。
在Mysql的InnoDB引擎中就是指在已提交读(READ COMMITTD)和可重复读(REPEATABLE READ)这两种隔离级别下的事务对于SELECT操做会访问版本链中的记录的过程。
这就使得别的事务能够修改这条记录,反正每次修改都会在版本链中记录。SELECT能够去版本链中拿记录,这就实现了读-写,写-读的并发执行,提高了系统的性能。
咱们的数据库当中如何作的优化?
说一下mybaits和hibernate的区别。
共同点:
MyBaits和HiBernate都是经过ORM对象关系映射框架,都是持久层数据框架。
不一样点:
Hibernate状态的转换关系。
最新的Hibernate文档中为Hibernate对象定义了四种状态(原来是三种状态,面试的时候基本上问的也是三种状态),分别是:瞬时态(new, or transient)、持久态(managed, or persistent)、游离态(detached)和移除态(removed,之前Hibernate文档中定义的三种状态中没有移除态),以下图所示,就之前的Hibernate文档中移除态被视为是瞬时态。
这个对象所保存的数据与数据库没有任何关系,除非经过Session的save()、saveOrUpdate()、persist()、merge()方法把瞬时态对象与数据库关联,并把数据插入或者更新到数据库,这个对象才转换为持久态对象。
对持久态对象进行delete操做后,数据库中对应的记录将被删除,那么持久态对象与数据库记录再也不存在对应关系,持久态对象变成移除态(能够视为瞬时态)。
持久态对象被修改变动后,不会立刻同步到数据库,直到数据库事务提交。
游离态的对象与临时状态对象是十分类似的,只是它还含有持久化标识。
说一下Spring的理解,IOC和AOP在项目里是怎么用的。
Spring是一个开源框架,处于MVC模式中的控制层,它能应对需求快速的变化,其主要缘由它有一种面向切面编程(AOP)的优点,其次它提高了系统性能,由于经过依赖倒置机制(IOC),系统中用到的对象不是在系统加载时就所有实例化,而是在调用到这个类时才会实例化该类的对象,从而提高了系统性能。
这两个优秀的性能使得Spring受到许多J2EE公司的青睐,如阿里里中使用最多的也是Spring相关技术。
Spring的优势:
Spring中AOP技术是设计模式中的动态代理模式,只需实现jdk提供的动态代理接口InvocationHandler,全部被代理对象的方法都由InvocationHandler接管实际的处理任务。
面向切面编程中还要理解切入点、切面、通知、织入等概念。
AOP的两种实现方式,而且说一下哪个效率更高一些,为何。
两种方式:一种是JDK动态代理,另外一种是CGLib的方式。
JDK动态代理具体实现原理:
JDK动态代理是面向接口的代理模式,若是被代理目标没有接口那么Spring也无能为力,Spring经过Java的反射机制生产被代理接口的新的匿名实现类,重写了其中AOP的加强方法。
CGLib动态代理:
CGLib是一个强大、高性能的Code生产类库,能够实现运行期动态扩展java类,Spring在运行期间经过 CGlib继承要被动态代理的类,重写父类的方法,实现AOP面向切面编程呢。
二者对比:
JDK动态代理是面向接口的。
CGLib动态代理是经过字节码底层继承要代理类来实现(若是被代理类被final关键字所修饰,那么抱歉会失败)。
性能:
关于二者之间的性能的话,JDK动态代理所建立的代理对象,在之前的JDK版本中,性能并非很高,虽然在高版本中JDK动态代理对象的性能获得了很大的提高,可是他也并非适用于全部的场景。
主要体如今以下的两个指标中:
说一些Spring的事务传播机制。
传播记住有以下几种:
public interface TransactionDefinition { int PROPAGATION_REQUIRED = 0; int PROPAGATION_SUPPORTS = 1; int PROPAGATION_MANDATORY = 2; int PROPAGATION_REQUIRES_NEW = 3; int PROPAGATION_NOT_SUPPORTED = 4; int PROPAGATION_NEVER = 5; int PROPAGATION_NESTED = 6;}
经常使用的主要有Required,RequiresNew,Nested三种。
若是想事务一块儿执行能够用Required知足大部分场景,若是不想让执行的子事务的结果影响到父事务的提交能够将子事务设置为RequiresNew。
你有什么想问个人么?
咱们京东\百度平时有技术分享这样的活动么?
有的你放心,技术分享咱们都会不一样的同事轮流进行不一样技术栈的分享。
好的,那我没什么问题了,期待能和您一块儿共事。
全部的题目都是粉丝提供的面试真题,我把全部的题目都查了下答案总结了一下,其实你们能够看出,不少题目都是我平时文章写的内容,我基本上就是跟着面试的思路写的。
并且面试的题目都很基础,是否是以为京东百度的面试其实也不难,咱们好好准备下真心随便进的那种,都是基础,其实平时多留心下,都不须要突击啥的。
好了各位,以上就是这篇文章的所有内容了,我是敖丙,励志作一名让你们都记得住的博主,能看到这里的人呀,都是人才。
我后面会每周都更新几篇一线互联网大厂面试和经常使用技术栈相关的文章,很是感谢人才们能看到这里,若是这个文章写得还不错,以为「敖丙」我有点东西的话 求点赞👍 求关注❤️ 求分享👥 对暖男我来讲真的 很是有用!!!
白嫖很差,创做不易,各位的支持和承认,就是我创做的最大动力,咱们下篇文章见!
敖丙 | 文 【原创】
若是本篇博客有任何错误,请批评指教,不胜感激 !
文章每周持续更新,能够微信搜索「 三太子敖丙 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/JavaFamily 已经收录,有一线大厂面试点思惟导图,也整理了不少个人文档,欢迎Star和完善,你们面试能够参照考点复习,但愿咱们一块儿有点东西。