《大厂面试》京东+百度一面,不当心都拿了Offer

你知道的越多,你不知道的越多

点赞再看,养成习惯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修饰静态方法,其实是对该类对象加锁,俗称“类锁”。

  • 对象锁钥匙只能有一把才能互斥,才能保证共享变量的惟一性
  • 在静态方法上的锁,和 实例方法上的锁,默认不是一样的,若是同步须要制定两把锁同样。
  • 关于同一个类的方法上的锁,来自于调用该方法的对象,若是调用该方法的对象是相同的,那么锁必然相同,不然就不相同。好比 new A().x() 和 new A().x(),对象不一样,锁不一样,若是A的单利的,就能互斥。
  • 静态方法加锁,能和全部其余静态方法加锁的 进行互斥
  • 静态方法加锁,和xx.class 锁效果同样,直接属于类的
看你熟悉单例,介绍下单例模式而且说下单例懒汉式和饿汉式的区别?(手写)

单例的介绍:

意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

主要解决:一个全局使用的类频繁地建立与销毁。

什么时候使用:当您想控制实例数目,节省系统资源的时候。

如何解决:判断系统是否已经有这个单例,若是有则返回,若是没有则建立。

关键代码:构造函数是私有的。

应用实例:

  • 一个班级只有一个班主任。
  • Windows 是多进程多线程的,在操做一个文件的时候,就不可避免地出现多个进程或线程同时操做一个文件的现象,因此全部文件的处理必须经过惟一的实例来进行。
  • 一些设备管理器经常设计为单例模式,好比一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。

优势:

  • 在内存里只有一个实例,减小了内存的开销,尤为是频繁的建立和销毁实例(好比管理学院首页页面缓存)。
  • 避免对资源的多重占用(好比写文件操做)。

缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

使用场景:

  • 要求生产惟一序列号。
  • WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
  • 建立的一个对象须要消耗的资源过多,好比 I/O 与数据库的链接等。

注意事项: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收集器对CPU资源很是敏感。在并发阶段,它虽然不会致使用户线程停顿,可是会由于占用了一部分线程而致使应用程序变慢,总吞吐量会下降。
  • CMS收集器没法处理浮动垃圾,可能会出现“Concurrent Mode Failure(并发模式故障)”失败而致使Full GC产生。

浮动垃圾:因为CMS并发清理阶段用户线程还在运行着,伴随着程序运行天然就会有新的垃圾不断产生,这部分垃圾出现的标记过程以后,CMS没法在当次收集中处理掉它们,只好留待下一次GC中再清理。这些垃圾就是“浮动垃圾”。

  • CMS是一款“标记--清除”算法实现的收集器,容易出现大量空间碎片。当空间碎片过多,将会给大对象分配带来很大的麻烦,每每会出现老年代还有很大空间剩余,可是没法找到足够大的连续空间来分配当前对象,不得不提早触发一次Full GC。

G1是一款面向服务端应用的垃圾收集器。G1具有以下特色:

  • 并行于并发:G1能充分利用CPU、多核环境下的硬件优点,使用多个CPU(CPU或者CPU核心)来缩短stop-The-World停顿时间。部分其余收集器本来须要停顿Java线程执行的GC动做,G1收集器仍然能够经过并发的方式让java程序继续执行。
  • 分代收集:虽然G1能够不须要其余收集器配合就能独立管理整个GC堆,可是仍是保留了分代的概念。它可以采用不一样的方式去处理新建立的对象和已经存活了一段时间,熬过屡次GC的旧对象以获取更好的收集效果。
  • 空间整合:与CMS的“标记--清理”算法不一样,G1从总体来看是基于“标记整理”算法实现的收集器;从局部上来看是基于“复制”算法实现的。
  • 可预测的停顿:这是G1相对于CMS的另外一个大优点,下降停顿时间是G1和CMS共同的关注点,但G1除了追求低停顿外,还能创建可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片断内,
  • 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(可串行化)

这是最高的隔离级别,它经过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每一个读的数据行上加上共享锁。在这个级别,可能致使大量的超时现象和锁竞争。这四种隔离级别采起不一样的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:

  • 脏读(Drity Read):某个事务已更新一份数据,另外一个事务在此时读取了同一份数据,因为某些缘由,前一个RollBack了操做,则后一个事务所读取的数据就会是不正确的。
  • 不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这多是两次查询过程当中间插入了一个事务更新的原有的数据。
  • 幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例若有一个事务查询了几列(Row)数据,而另外一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就有几列数据是未查询出来的,若是此时插入和另一个事务插入的数据,就会报错。
什么是MVCC,主要是为了作什么?

MVCC(Mutil-Version Concurrency Control),就是多版本并发控制。MVCC 是一种并发控制的方法,通常在数据库管理系统中,实现对数据库的并发访问。

在Mysql的InnoDB引擎中就是指在已提交读(READ COMMITTD)和可重复读(REPEATABLE READ)这两种隔离级别下的事务对于SELECT操做会访问版本链中的记录的过程。

这就使得别的事务能够修改这条记录,反正每次修改都会在版本链中记录。SELECT能够去版本链中拿记录,这就实现了读-写,写-读的并发执行,提高了系统的性能。

咱们的数据库当中如何作的优化?
  • 对查询进行优化,要尽可能避免全表扫描,首先应考虑在 where 及 order by 涉及的列上创建索引。
  • 应尽可能避免在 where 子句中对字段进行 null 值判断,不然将致使引擎放弃使用索引而进行全表扫描
  • 应尽可能避免在 where 子句中使用 != 或 <> 操做符,不然将引擎放弃使用索引而进行全表扫描。
  • 应尽可能避免在 where 子句中使用 or 来链接条件,若是一个字段有索引,一个字段没有索引,将致使引擎放弃使用索引而进行全表扫描
  • in 和 not in 也要慎用,不然会致使全表扫描
  • like模糊全匹配也将致使全表扫描
说一下mybaits和hibernate的区别。

共同点:

MyBaits和HiBernate都是经过ORM对象关系映射框架,都是持久层数据框架。

不一样点:

  • HiBernate它重量级的框架,而MyBaits是轻量级的框架。
  • HiBernate对JDBC的封装比较深,对开发者些sql的能力不是很高,只须要经过Hql语句操做对象便可完成数据的持久化操做了。
  • MyBaits也是对JDBC的封装,可是没有Hibernate那么深,它的sql语句,都再配置里,能够经过重写配置里sql,来实现数据优化,实施起来也比较方便。
  • 处理大数据的时候,建议使用MyBaits它优化sql语句更方便。
Hibernate状态的转换关系。

最新的Hibernate文档中为Hibernate对象定义了四种状态(原来是三种状态,面试的时候基本上问的也是三种状态),分别是:瞬时态(new, or transient)、持久态(managed, or persistent)、游离态(detached)和移除态(removed,之前Hibernate文档中定义的三种状态中没有移除态),以下图所示,就之前的Hibernate文档中移除态被视为是瞬时态。

  • 瞬时态:当new一个实体对象后,这个对象处于瞬时态,即这个对象只是一个保存临时数据的内存区域,若是没有变量引用这个对象,则会被JVM的垃圾回收机制回收。

    这个对象所保存的数据与数据库没有任何关系,除非经过Session的save()、saveOrUpdate()、persist()、merge()方法把瞬时态对象与数据库关联,并把数据插入或者更新到数据库,这个对象才转换为持久态对象。

  • 持久态:持久态对象的实例在数据库中有对应的记录,并拥有一个持久化标识(ID)。

    对持久态对象进行delete操做后,数据库中对应的记录将被删除,那么持久态对象与数据库记录再也不存在对应关系,持久态对象变成移除态(能够视为瞬时态)。

    持久态对象被修改变动后,不会立刻同步到数据库,直到数据库事务提交。

  • 游离态:当Session进行了close()、clear()、evict()或flush()后,实体对象从持久态变成游离态,对象虽然拥有持久和与数据库对应记录一致的标识值,可是由于对象已经从会话中清除掉,对象不在持久化管理以内,因此处于游离态(也叫脱管态)。

    游离态的对象与临时状态对象是十分类似的,只是它还含有持久化标识。

说一下Spring的理解,IOC和AOP在项目里是怎么用的。

Spring是一个开源框架,处于MVC模式中的控制层,它能应对需求快速的变化,其主要缘由它有一种面向切面编程(AOP)的优点,其次它提高了系统性能,由于经过依赖倒置机制(IOC),系统中用到的对象不是在系统加载时就所有实例化,而是在调用到这个类时才会实例化该类的对象,从而提高了系统性能。

这两个优秀的性能使得Spring受到许多J2EE公司的青睐,如阿里里中使用最多的也是Spring相关技术。

Spring的优势:

  • 下降了组件之间的耦合性,实现了软件各层之间的解耦。
  • 可使用容易提供的众多服务,如事务管理,消息服务,日志记录等。
  • 容器提供了AOP技术,利用它很容易实现如权限拦截、运行期监控等功能。

Spring中AOP技术是设计模式中的动态代理模式,只需实现jdk提供的动态代理接口InvocationHandler,全部被代理对象的方法都由InvocationHandler接管实际的处理任务。

面向切面编程中还要理解切入点、切面、通知、织入等概念。

AOP的两种实现方式,而且说一下哪个效率更高一些,为何。

两种方式:一种是JDK动态代理,另外一种是CGLib的方式。

JDK动态代理具体实现原理:

  • 经过实现InvocationHandlet接口建立本身的调用处理器;
  • 经过为Proxy类指定ClassLoader对象和一组interface来建立动态代理;
  • 经过反射机制获取动态代理类的构造函数,其惟一参数类型就是调用处理器接口类型;
  • 经过构造函数建立动态代理类实例,构造时调用处理器对象做为参数参入;

JDK动态代理是面向接口的代理模式,若是被代理目标没有接口那么Spring也无能为力,Spring经过Java的反射机制生产被代理接口的新的匿名实现类,重写了其中AOP的加强方法。

CGLib动态代理:

CGLib是一个强大、高性能的Code生产类库,能够实现运行期动态扩展java类,Spring在运行期间经过 CGlib继承要被动态代理的类,重写父类的方法,实现AOP面向切面编程呢。

二者对比:

JDK动态代理是面向接口的。

CGLib动态代理是经过字节码底层继承要代理类来实现(若是被代理类被final关键字所修饰,那么抱歉会失败)。

性能:

关于二者之间的性能的话,JDK动态代理所建立的代理对象,在之前的JDK版本中,性能并非很高,虽然在高版本中JDK动态代理对象的性能获得了很大的提高,可是他也并非适用于全部的场景。

主要体如今以下的两个指标中:

  • CGLib所建立的动态代理对象在实际运行时候的性能要比JDK动态代理高很多,有研究代表,大概要高10倍;
  • 可是CGLib在建立对象的时候所花费的时间却比JDK动态代理要多不少,有研究代表,大概有8倍的差距;
  • 所以,对于singleton的代理对象或者具备实例池的代理,由于无需频繁的建立代理对象,因此比较适合采用CGLib动态代理,反正,则比较适用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;}
  • PROPAGATION_REQUIRED:若是当前没有事务,就新建一个事务,若是已经存在一个事务中,加入到这个事务中。这是最多见的选择。
  • PROPAGATION_SUPPORTS:支持当前事务,若是当前没有事务,就以非事务方式执行。
  • PROPAGATION_MANDATORY:使用当前的事务,若是当前没有事务,就抛出异常。
  • PROPAGATION_REQUIRES_NEW:新建事务,若是当前存在事务,把当前事务挂起。
  • PROPAGATION_NOT_SUPPORTED:以非事务方式执行操做,若是当前存在事务,就把当前事务挂起。
  • PROPAGATION_NEVER:以非事务方式执行,若是当前存在事务,则抛出异常。
  • PROPAGATION_NESTED:若是当前存在事务,则在嵌套事务内执行。若是当前没有事务,则执行与PROPAGATION_REQUIRED相似的操做。

经常使用的主要有Required,RequiresNew,Nested三种。

  • Required:简单理解就是事务方法会判断是否存在事务,有事务就用已有的,没有就从新开启一个。
  • RequiresNew:简单理解就是开启新事务,若当前已有事务,挂起当前事务。新开启的事务和以前的事务无关,拥有本身的锁和隔离级别,能够独立提交和回滚,内层事务执行期间,外层事务挂起,内层事务执行完成后,外层事务恢复执行。
  • Nested:简单理解就是嵌套事务,若是外部事务回滚,则嵌套事务也会回滚!!!外部事务提交的时候,嵌套它才会被提交。嵌套事务回滚不会影响外部事务。子事务是上层事务的嵌套事务,在子事务执行以前会创建savepoint,嵌套事务的回滚会回到这个savepoint,不会形成父事务的回滚。

若是想事务一块儿执行能够用Required知足大部分场景,若是不想让执行的子事务的结果影响到父事务的提交能够将子事务设置为RequiresNew。

你有什么想问个人么?

咱们京东\百度平时有技术分享这样的活动么?

有的你放心,技术分享咱们都会不一样的同事轮流进行不一样技术栈的分享。

好的,那我没什么问题了,期待能和您一块儿共事。

总结

全部的题目都是粉丝提供的面试真题,我把全部的题目都查了下答案总结了一下,其实你们能够看出,不少题目都是我平时文章写的内容,我基本上就是跟着面试的思路写的。

并且面试的题目都很基础,是否是以为京东百度的面试其实也不难,咱们好好准备下真心随便进的那种,都是基础,其实平时多留心下,都不须要突击啥的。

点关注,不迷路

好了各位,以上就是这篇文章的所有内容了,我是敖丙,励志作一名让你们都记得住的博主,能看到这里的人呀,都是人才

我后面会每周都更新几篇一线互联网大厂面试和经常使用技术栈相关的文章,很是感谢人才们能看到这里,若是这个文章写得还不错,以为「敖丙」我有点东西的话 求点赞👍 求关注❤️ 求分享👥 对暖男我来讲真的 很是有用!!!

白嫖很差,创做不易,各位的支持和承认,就是我创做的最大动力,咱们下篇文章见!

敖丙 | 文 【原创】

若是本篇博客有任何错误,请批评指教,不胜感激 !


文章每周持续更新,能够微信搜索「 三太子敖丙 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/JavaFamily 已经收录,有一线大厂面试点思惟导图,也整理了不少个人文档,欢迎Star和完善,你们面试能够参照考点复习,但愿咱们一块儿有点东西。

相关文章
相关标签/搜索