首页 > 快手后端Java开发一面面经
头像
今天你摸鱼了吗?
编辑于 2020-09-26 09:58
+ 关注

快手后端Java开发一面面经

面试官人很好,有引导,会对你的错误给出提示,体验很好。
编程题是放在中间的,有些问题是递进抛出来的,我这里大概整理了一下。

  1. 自我介绍
    面试官那边似乎只能看到我的实习经历,看不到我的项目经历,所以就简单的走个过场。

  2. 基本数据类型相关

    • 说出java有哪几种基本数据类型。

      int,long,double,float,char,boolean,short,byte。注意String不是基本数据类型

    • int long占多少位?int的范围。

      int占32位,long占64为。int范围-2^31 ~ 2^31-1。

    • 浮点数double如何表示0.2?
      因为记不起具体的IEEE754标准了,所以我只大概回答了0.2 = 1/8 + ....这样的形式。这里附上IEEE754的wiki:
      摘自wiki
      摘自wiki

      S为符号位,Exp为指数字,Fraction为有效数字。指数部分即使用所谓的偏正值形式表示,偏正值为实际的指数大小与一个固定值(64位的情况是1023)的和。采用这种方式表示的目的是简化比较。因为,指数的值可能为正也可能为负,如果采用补码表示的话,全体符号位S和Exp自身的符号位将导致不能简单的进行大小比较。正因为如此,指数部分通常采用一个无符号的正数值存储。双精度的指数部分是−1022~+1023加上1023,指数值的大小从1~2046(0(2进位全为0)和2047(2进位全为1)是特殊值)。浮点小数计算时,指数值减去偏正值将是实际的指数大小。

    • 两个new Integer(127)使用==操作符比较的结果。

      false,虽然java内置-128 ~ 127的常量池,但是两个实例在堆上分配了不同的空间,==比较的是两个对象的地址是否相等,故不相等。

  3. Map

    • map有哪些,底层都是怎么实现的?扩容机制?

      这里面试官不谈并发,所以我只说了HashMap,TreeMap,LinkedHashMap
      1)jdk1.8之前,HashMap使用数组+链表实现;1.8之后,当链表数组长度过长时,会将其转化为红黑树(在此之前还会检查map的容量,若容量小于64,则先扩容进行重hash)。

      2)LinkedHashMap则是多维护了一条双向链表。

      3)TreeMap需要key实现compareTo或者提供一个Compactor比较器,TreeMap它还实现了NavigableMap接口和SortedMap接口。
      实现 NavigableMap 接口让 TreeMap 有了对集合内元素的搜索的能力。实现SortMap接口让 TreeMap 有了对集合中的元素根据键排序的能力

    • 讲讲并发的map:ConcurrentHashMap HashTable底层。
      HashTable是对整表加锁,现在基本被抛弃了。

      jdk1.8之前,ConcurrentHashMap采用分段锁(Segment),对不同段的Entry进行操作互不影响;
      jdk1.8之后,ConcurrentHashMap直接使用Node数组+链表+红黑树,通过synchronized和CAS来保证并发的可靠性。

    • 并发下的hashMap会有哪些安全问题?

      这里我只是简单的说了写覆盖跟不可重复读(联想到数据库了),面试官就放我过了。

    • 添加元素时头插还是尾插?

    1.7头插,1.8尾插。

  4. 并发相关

    • 刚刚你说了CAS,来讲讲CAS。

      CAS,compare and swap,在写入之前先比较对象已有值和预期值是否相同,只有对象当前值与预期值一致才赋值成功。

    • 讲讲乐观锁、悲观锁。

      乐观锁,认为其他线程不会修改值,所以不上锁,只在写入时候简单一下其他线程是否修改过。常见的实现方式有CAS版本号机制

      CAS前面已经提过了,他主要的缺点就是:
      1)自旋消耗CPU性能。
      2)ABA问题。

      版本号机制就是变量每次赋值时版本号+1,赋值之前先比较版本号是否一致,若不一致则代表该变量被修改过了,这能解决ABA问题。

    • 如何保证i++多线程下正确执行?

      使用AtomicInteger类的getAndIncrement方法,底层是去调用unsafe类的getAndAddInt方法,不断自旋直至成功为止。

    • 你刚刚提到了自旋,那他会一直自旋下去吗?

      不会,jvm有个参数指定了最大的自旋次数,超过这个次数线程就被挂起了。

    • 你刚刚提到了getAndIncrement,那底层实现他用了volatile,来说说volatile的作用。

      volatile主要有三特性:
      1)保证内存可见性
      2)不保证原子性
      3)防止指令重排序
      在这里主要是用于保证内存可见性,当一个线程写volatile变量时,会使得其他线程的缓存行失效,其他线程必须从主存中读取最新的值。

    • synchronized和Lock的区别。

      1)synchronized是关键字,Lock是一个接口
      2)synchronized是可重入的、独占的,而Lock只是一个接口,JDK提供ReeanLock、ReadWriteLock,但你完全可以遵从Lock+AQS的规范自己实现一个锁。
      3)synchronized是且只能是阻塞的,而Lock可以超时等待
      4)Lock需要手动释放锁,所以一般都会使用try...finally来确保锁的释放

    • synchronized上锁的几种情况。

      synchronized可以锁对象也可以锁函数,锁对象比较简单这里我们讨论锁函数的情况。
      1)synchronized修饰普通方***获取实例的锁。不同线程调用不同实例的同一方法不会阻塞,因为他们不会抢占一把锁。
      2)synchronized修饰static方法,锁的是Class对象。不同线程即使调用同一个类的两个synchronized static方法都会阻塞,因为他们会抢占Class的锁。
      3)无synchronized修饰的方法和synchronized修饰的普通方法不会互相阻塞,因为前者不需要获取锁。
      4)synchronized修饰的静态/非静态方法不会抢占锁,因为他们获取的锁不同。

  5. jvm
    这里只是简单的问了一下内存划分,把pc、虚拟机栈、本地方法栈、堆、方法区这些讲清楚就好了。

  6. 异常

    • 异常的类结构,分为哪几种,各举出几个例子。

      这一部分直接拉跨了,基本都是瞎答,好在老哥没为难我。
      转载自javaguide

    • error属于异常吗?举出你常见的异常。

      error不属于异常,StackOverflow和OOM是比较常见的Error。
      异常又分为checked和unchecked,运行时异常都属于unchecked,不需要手动捕获,checked异常需要手动捕获。

  1. 数据库:

    • 讲讲聚簇索引、联合索引、覆盖索引

      一般的教材都说聚簇索引是指物理顺序与索引顺序一致。在《Mysql技术内幕》里面提到了,聚簇索引并非严格要求物理顺序与索引顺序一致,因为这会导致性能下降。mysql通过双向链表维护页与页之间的关联、页内数据,只要维护好双向链表实现逻辑上的顺序一致即可
      Innodb采用聚簇索引,数据文件本身就是索引文件。而MyISAM是非聚簇索引,索引和数据分离。

      联合索引指对多个列建立索引,只有当查询满足最左前缀匹配原则索引才生效。这里面试官还让我讲清楚不满足最左前缀为什么不生效,当时没有工具结结巴巴了半天。
      假设有一联合索引(a,b,c),现有数据:(1,2,3),(2,1,4),(3,0,1)

      那么其在B+树中的位置应当如下:
      图片说明

      可以发现单独使用列b显然不符合搜索树的定义,故索引会失效。

    • 页大小,mysql是如何在某一页中找到数据的呢?

      16k。页内的行记录通过双向链表连接,一开始我说错了说的是二分查找,然后面试官提醒我链表可以二分吗我才反应过来不是二分查找。
      然后这里没转过来就说挨个挨个找,其实Mysql技术内幕中提到了Page Directory:

摘自Mysql技术内幕

  1. 算法题

    • 现在有两个很大的整数用String表示,返回两数相加之和。
  2. 逻辑题

    • A,B两人约定6-7点碰面,两人只会等对方15分钟,求两人相遇的概率。
      横轴表示A到的时间,纵轴表示B到的时间:
      图片说明
      两条红线之间的面积/总面积就是相遇概率,最终结果0.4375。

更多模拟面试

全部评论

(8) 回帖
加载中...
话题 回帖