2017面试题记录

2017-06-30 美团点评

DB

  1. 数据库索引类型?

    • normal:普通索引。
    • unique:唯一索引,不允许重复。
    • full text:全文索引,长文章搜索。
  2. 数据库索引的数据结构?适用范围?

    • Hash索引:一次定位,效率高,但是由于经过了Hash运算,只能满足等值过滤,如”=”/“!=”/“IN”查询,无法范围查询,非排序索引,遇到大量hash值相等的情况时性能下降严重(Hash碰撞问题)。
    • B-Tree索引:从根节点到枝节点遍历(平衡树),搜索性能相对稳定,常用。可以适用于范围查询,可排序。
  3. 数据库事务四大特性?

    ACID:

    • Atomic-原子性:整个数据库事务不可分割。
    • Consistency-一致性:事务不能破坏关系数据的完整性以及业务逻辑的一致性。例如对银行转帐事务,不管事务成功还是失败,应该保证事务结束后ACCOUNTS表中Tom和Jack的存款总额为2000元。
    • Isolation-隔离性:在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
    • Durability-持久性:只要事务成功结束,它对数据库所做的更新就必须永久保存下来。
  4. 什么是脏读、不可重复读、幻读?

    1. 脏读: 一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。

      1.Mary的原工资为1000, 财务人员将Mary的工资改为了8000(但未提交事务)

      2.Mary读取自己的工资 ,发现自己的工资变为了8000,欢天喜地!

      3.而财务发现操作有误,回滚了事务,Mary的工资又变为了1000像这样,Mary记取的工资数8000是一个脏数据。

    2. 不可重复读: 一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。

      1.在事务1中,Mary 读取了自己的工资为1000,操作并没有完成

      2.在事务2中,这时财务人员修改了Mary的工资为2000,并提交了事务.

      3.在事务1中,Mary 再次读取自己的工资时,工资变为了2000

      解决办法:如果只有在修改事务完全提交之后才可以读取数据,则可以避免该问题。

    3. 幻读: 当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

      目前工资为1000的员工有10人。

      1.事务1,读取所有工资为1000的员工。

      2.这时事务2向employee表插入了一条员工记录,工资也为1000

      3.事务1再次读取所有工资为1000的员工 共读取到了11条记录

      解决办法:如果在操作事务完成数据处理之前,任何其他事务都不可以添加新数据,则可避免该问题

      • 不可重复读的重点是修改: 同样的条件, 你读取过的数据,再次读取出来发现值不一样了
      • 幻读的重点在于新增或者删除: 同样的条件, 第 1 次和第 2 次读出来的记录数不一样
  5. 数据库事务隔离级别?解决什么问题?

隔离级别 脏读 不可重复读 幻读
读未提交 Y Y Y
读已提交 N Y Y
可重复读 N N Y
串行化 N N N
  1. ReadUncommitted:
    假设A事务即不发布共享锁,也不接受独占锁,那么并发的B或者其它事务可以改写A事务读取的数据,那么并发的C事务读取到的数据的状态和A的或者B的数据都可能不一致,那么。脏读、不可重复读、幻象数据都可能存在。

  2. ReadCommitted:
    假设A事务对正在读取数据Data放置了共享锁,那么Data不能被其它事务改写,所以当B事务对Data进行读取时总和A读取的Data数据是一致的,所以避免了脏读。由于在A没有提交之前可以对Data进行改写,那么B读取到的某个值可能会在其读取后被A更改从而导致了该值不能被重复取得;或者当B再次用相同的where字句时得到了和前一次不一样数据的结果集,也就是幻像数据。

  3. RepeatableRead:
    (注意MSDN原文中的第一句话:在查询中使用的所有数据上放置锁,所以不存在脏读的情况)。
    假设A事务对读取的所有数据Data放置了锁,以阻止其它事务对Data的更改,在A没有提交之前,新的并发事务读取到的数据如果存在于Data中,那么该数据的状态和A事务中的数据是一致的,从而避免了不可重复的读取。但在A事务没有结束之前,B事务可以插入新记录到Data所在的表中,那么其它事务再次用相同的where字句查询时,得到的结果数可能上一次的不一致,也就是幻像数据。

  4. Serializable:
    在数据表上放置了排他锁,以防止在事务完成之前由其他用户更新行或向数据集中插入行,这是最严格的锁。它防止了脏读、不可重复读取和幻象数据。

http://uule.iteye.com/blog/1109647

https://tech.meituan.com/innodb-lock.html

Java

jvm这一块比较熟悉,不做详细记录了。

  1. jvm类加载器?

    双亲委托模型:具有优先级的层次关系。

    启动类加载器<–扩展类加载器<–应用程序类加载器<–自定义类加载器

  2. jvm gc新生代、老年代?

    新生代:老年代=1:2

    Eden:Survivor=8:1:1

  3. jvm gc实现方式?

    新生代:复制
    老年代:标记-清除

  4. struts2/spring mvc实现原理?

前端

  1. javascript闭包?

2017-07-05 哔哩哔哩

  1. ConcurrentHashMap实现原理?

    分离锁+不可变+volatile

    将整个Map分隔为一组Segment,Segment结构与HashMap相似,其中是链表形式的HashBucket。

    Segment个数:concurrencyLevel,并发级别,默认为16。

    put操作时,针对单个Segment加锁而不是整个ConcurrentHashMap。

    get操作时,由于HashEntry不可变,其中value被定义为volatile,所以无需加锁。

    所以理论上,ConcurrentHashMap可以支持Segment数目个线程并发写,任意数量线程并发读。

    http://wiki.jikexueyuan.com/project/java-collection/concurrenthashmap.html

  2. java内存堆、栈?什么命令打印java内存快照?

  3. tomcat调优?

    1. jvm层面

      • server模式
      • Xms-Xmx设为一致
      • -XX:+UseParNewGC使用并行gc
      • -XX:+UseConcMarkSweepGC使用cms gc
    2. tomcat容器层面

      • 线程池个数设置
      • gzip压缩
      • 超时时间
      • 禁用DNS查询
  4. 分布式设计CAP理论?

    Consistence一致性/Availability可用性/Partitioning分区容错性,最多只能满足2项。

2017-07-11 爱奇艺

  1. HashMap原理?

    单纯数组:寻址快速,但插入、删除性能差;存储区域连续,占用内存严重。

    单纯链表:寻址困难,但插入、删除性能差。

    HashMap的底层主要是基于数组和链表来实现的,综合二者特性。它之所以有相当快的查询速度主要是因为它是通过计算散列码来决定存储的位置。

    关键方法:

    final int hash(Object k) 保证hash结果均匀分布

    static int indexFor(int h, int length) 利用位运算取低位(相当于取模),快速定位数组下标

    http://blog.csdn.net/jianyuerensheng/article/details/51579091

  2. i++是否线程安全?java.atomic包?

    java.atomic.AtomicInteger#getAndIncrement()

  3. java锁?可重入锁?

2017-08-01 沪江网

  1. 为什么说HashMap是线程不安全的?

    HashMap底层存储是一个Entry数组,Entry是一个链表,来解决hash碰撞。所以有以下线程问题:

    1. put()/remove()
      多线程调用put()/remove()方法并发生hash碰撞时,操作了同一个Entry链表,put()是将value加入表头,remove()是查找链表中节点删除,在put/remove方法未同步的情况下,会出现部分线程操作丢失的情况。
    2. resize()
      多线程同时触发扩容条件resize()时,各个线程将各自生成新的Entry数组并且rehash后,将其赋给底层table,那么可能出现只有一个线程的新数组成功赋给table,其他操作丢失的情况。
  2. ConcurrentHashMap.size()如何实现?

    前提:segment中有一个变量modCount来记录修改segment的次数,虽然这个实际值会超过int值的上线,但也起到了短时间内的参考作用。

    循环执行:

    1. 先在不加锁的情况下尝试累加各个segment.modCount与segment.count
    2. 如果modCount的总和与上次循环相等,那么则认为此时map没有被修改,可以直接返回count的总和
    3. 如果modCount的总和与上次循环不相等,那么则认为map被修改了,需要重新循环来计算size
    4. 如果循环次数超过了RETRIES_BEFORE_LOCK变量,默认为2,那么将对所有segment加锁,再累加count
    5. 释放所有的segment锁,返回size
  3. DCL双检查锁单例模式为什么线程不安全?

  4. atomic CAS?

  5. static class能否包含非static方法?

2017-08-09 蚂蚁金服

  1. hibernate对比mybatis?

    • hibernate是ORM,着重POJO和数据库表之间的映射;mybatis是SQL mapping,着重POJO与SQL映射。
    • hibernate上手难度大,能自动建模、自动生成SQL,快速开发;mybatis对高级查询更加灵活。
    • hibernate自动生成SQL,代码与数据库无关,理论上可移植性强于手动编写SQL的mybatis。
    • hibernate查询全部字段,mybatis可以指定查询字段,性能稍好。
    • mybatis直接面对sql,利于性能调优。
  2. 第三方支付回调防丢失?