同花顺一面面经

面经

写面经,攒人品

  1. 自我介绍
  2. jvm
    1. 堆内存溢出
      1. 怎么快速的堆内存溢出
      2. 溢出怎么防止
      3. 为什么会堆内存溢出
      4. 不段创建String对象,和不断创建线程造成溢出的区别?
      5. 怎么分析,dump内存文件
      6. 分析hprof文件,有那些内容
    2. 栈指针溢出
      1. 怎么快速的栈指针溢出
      2. 怎么防止
      3. 为什么会栈指针溢出
    3. 垃圾回收器
      1. 你们用的垃圾回收器
      2. 你知道的垃圾回收器
      3. 讲一讲过程,区别(CMS,G1)
  3. redis分布式锁实现
  4. mysql索引,为什么需要索引,自己的理解
  5. mysql索引的数据结构
  6. 你们数据量级,一次处理的数据量
  7. 线程池,几个核心参数的作用,不背原理
  8. hashmap和hashtable的区别
  9. dubbo如何实现高可用的
  10. 反问

解答

redis分布式锁的实现

mysql索引,为什么需要索引

  mysql索引的最大最用就在于提高查询效率,原理在数据结构中,索引在提高查询效率的同时降低了修改的效率。

mysql索引的数据结构

  索引数据的组织结构和数据的组织结构是一样的,都是B+树的结构,区别在于他们的叶子节点所存储的数据,数据存储文件中叶子节点中存储着主键索引和表中的数据,而索引保存文件中,叶子节点则存储着索引字段以及对应的主键id值。
  当通过素引进行查询时,会先根据索引查询出主键id的值,在在数据保存文件中,根据id查出所需要的数据,这个过程叫做回表。

线程池理解(corepoolsize)

  • threadpool
  • threadpool
      个人理解,核心线程数,就相当于车间里面的流水线数,就是正常情况下运行的流水线数,最大的线程数,就是再有紧急订单的情况下,我们在正常的流水线上,扩充到的流水线数。

hashmap和hashtable

  hashmap和hashtable的区别有几点:

  • 继承和实现方式不同
    • hashmap实现的是map接口
    • hashtable实现的是map接口继承的Dictionary类
  • 线程安全不同
    • hashmap线程不安全
    • hashtable线程安全,在每个方法中都加入Synchronize方法。
  • 对null的处理不同
    • hashtable键与值均不允许null
    • hashmap均可以null,null为键只会有一个
  • 支持的遍历种类不同
    • Hashtable、HashMap都使用了Iterator。
    • 而由于历史原因,Hashtable还使用了Enumeration的方式 。
  • 通过Iterator迭代器遍历时,遍历的顺序不同
    • hashmap采用fail-fast机制
    • hashtable在1.8以后才用了fail-fast机制
  • 容量的初始值和增加方式都不一样
    • hashmap初始16,扩容为2倍
    • hashtable为11,扩容为2*N+1
  • 添加key-value时的hash值算法不同
    • haspmap采用key的hashcode确定位置
    • hashtable采用对象的hashcode,然后对长度才用除留余数法确定位置

dubbo如何实现高可用

  dubbo通过一系列手段实现了,高可用。

  • zookeeper宕机与dubbo直连
    • zookeeper注册中心宕机,还可以消费dubbo暴露的服务
      • 监控中心宕掉不影响使用,只是丢失部分采样数据
      • 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
      • 注册中心对等集群,任意一台宕掉后,将自动切换到另一台
      • 注册中心全部宕机后,可以通过本地缓存进行通信,(直连)
      • 服务提供者无状态,任意一台宕掉后,不影响使用
      • 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复
  • 集群下的负载均衡
    • 带权重的随机
    • 带权重的轮询
    • 最少活跃数
    • 一致性hash
  • 服务降级
  • 集群容错机制
    • Failover Cluster:失败自动切换
    • Failfast Cluster:快速失败,失败则立即报错
    • Failsafe Cluster:安全失败,失败就会忽略
    • Failback Cluster:失败自动恢复,会定时重发
    • Forking Cluster:并行调用,只需一个成功返回
    • Broadcast Cluster:广播调用,逐个调用每个提供者,任意一台报错则报错

JVM

堆内存溢出

怎么快速的堆内存溢出?

  通过jvm参数去设置堆内存大小,然后再循环里面不断的创建线程,直到报OutOfMemory异常。

堆内存溢出怎么防止?

  最直接的办法就是直接调整堆内存的大小,也有一写在编写代码过程中注意的,防止内存溢出:

  • 尽早释放无用对象的引用
  • 程序进行字符串处理时,尽量避免使用String,而应该使用StringBuffer
  • 尽量少用静态变量(全局的,存在方法区,不会被回收)
  • 避免集中创建对象,尤其是大对象,如果可以的话尽量使用流操作
  • 尽量运用对象池技术以提高系统性能
  • 不要在经常调用的方法中创建对象,尤其忌讳在循环中创建对象
  • 优化配置
    • 从代码层面进行优化完善,尽量避免该情况发生
    • 调整优化服务器配置:
      • 设置-Xms、-Xmx等
      • 设置NewSize、MaxNewSize相等
      • 设置Heap size,PermGen space

  可以通过一些手段保证代码安全:

  • 是否应用中的类中和引用变量过多使用了Static修饰
  • 是否应用中使用了大量的递归或无限递归(递归中创建对象)
  • 是否App中使用了大量循环或死循环(循环中创建对象)
  • 检查应用中是否使用了向数据库查询所有记录的方法
  • 检查是否有数组,List,Map中存放的是对象的引用而不是对象(这些引用会使得对象无法被释放)
  • 检查是否使用了“非字面量字符串进行+”的操作,String对象每次+

为什么会堆内存溢出?

  内存大小不够;是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory。

不断创建String和不断创建线程造成内存溢出的区别?

  本质上,创建String就是创建了一个对象,分配了一块内存空间,而创建线程,则也会创建线程对象(Thread类的对象),区别在于创建线程的对象中,会包含一些线程的相关信息,也就是区别在线程对象的信息和普通对象的信息不同。

怎么分析,dump内存文件

  一般有两种方法,自动和手动。

  • jvm参数:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/admin/logs/java.hprof
  • jmap -dump:format=b,file=/home/admin/logs/heap.hprof javapid

  dump内存文件后,可以通过一些工具进行分析。

  • mat
  • visual VM
  • JProfiler

栈指针溢出

怎么快速栈指针溢出?

  通过死循环内调用方法,或者递归没有出口,无限递归,造成StackOverFlow异常。

怎么防止栈指针溢出?

  通过一些判断,保证代码安全,破坏栈指针溢出的条件:

  • 是否有递归调用
  • 是否有大量循环或者死循环
  • 全局变量是否过多
  • 数组、List、map数据是否过大
  • 使用DDMS工具进行查找大概出现栈溢出的位置

为什么为栈指针溢出?

  栈指针溢出其实可以分为两种,不过一般说的是第一种,本质都是由内存不足引起的。

  • 线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError
  • 虚拟机在扩展栈深度时无法申请到足够的内存空间,将抛出OutOfMemberError

垃圾回收器

你们用的垃圾回收器?你知道的垃圾回收器?CMS和G1的区别?


参考文献 & 鸣谢