Day01-牛客面经篇

70 阅读4分钟

来源:www.nowcoder.com/discuss/440…

集合类

  1. HashMa为什么不是线程安全的?
  2. HashMap扩容流程是否是线程安全的,为什么?
  3. 如何设计线程安全的HashMap?
  4. CAS机制在ConcurrentHashMap中的具体体现?

答 :

  1. hashmap不是线程安全的,他源码里面没有加线程安全的处理
  2. 扩容流程不安全,多线程操作下可能会引入扩容死链(1.7),数据丢失(1.7、1.8)
  3. 可以仿照ConcurrentHashMap设计,引入CAS和synchronized锁机制

Redis

  1. Redis如何实现分布式锁?
  2. Redis去重方式了解几种,每种方式的优缺点?
  3. 讲一讲布隆过滤器?

答:

  1. 使用了set命令有个nx参数可以实现【key 不存在插入】,用它来实现分布式锁,需要考虑很多问题,怎么加锁、怎么释放锁、加锁线程和释放锁线程是否是一个。
  2. 可以用redis数据类型set、zset、HyperLogLog、布隆过滤器
  3. 布隆过滤器就相当于一个位图数组,初始值里面都是0,然后一些hash函数,先用hash函数在位图数组上标记,当我们要判断这个元素是否存在时,我们通过这些hash函数算出这个元素的一些hash值映射到数组上判断他是否为1,若有一个0则不存在。

JVM

  1. 有做过JVM调优吗?讲一个JVM调优的具体案例?
  2. 说一下JVM调优的命令?
  3. 线上服务CPU占用过高怎么排查?

答:

  1. 一个常见的JVM调优案例是调整内存大小。如果应用程序在运行中经常出现OutOfMemoryError错误,可能是因为堆内存不够用了。这时可以通过增加堆内存来解决这个问题。可以通过调整 -Xmx 和 -Xms 参数来调整堆内存的大小。 例如: -Xmx1024m -Xms1024m 这样可以将堆内存设置为1GB,并且初始堆内存和最大堆内存都设置为1GB。 另外,如果程序频繁出现Full GC,可能是因为新生代内存不够用了,可以通过调整-XX:NewSize和-XX:MaxNewSize来调整新生代内存的大小。 这只是JVM调优的一个方面,具体应用还需要根据不同场景来进行调整.
  1. JVM调优的命令有很多,常用的有:
  • -Xmx: 设置最大堆内存
  • -Xms: 设置初始堆内存
  • -XX:NewSize: 设置新生代内存大小
  • -XX:MaxNewSize: 设置新生代最大内存
  • -XX:SurvivorRatio: 设置新生代eden空间和survivor空间的比例
  • -XX:+PrintGCDetails: 打印GC详细信息
  • -XX:+PrintGCTimeStamps: 打印GC时间戳
  • -XX:+PrintTenuringDistribution: 打印年龄分布信息
  • -XX:+PrintGCApplicationStoppedTime:打印应用程序停顿时间信息 这些命令都是以“-XX:”开头的,可以在启动JVM时传入这些参数来调整JVM的运行状态.

怎么排查?

  1. 检查系统负载:通过命令 tophtop 查看 CPU 和内存使用情况。如果系统负载过高,可能是因为系统资源不足。
  2. 检查进程:使用命令 ps -efpstree 查看进程使用情况。通过查看进程的 CPU 和内存使用情况,可以确定哪个进程导致 CPU 占用过高。
  3. 分析日志:检查应用程序的日志,看看是否有任何异常输出。如果发现了异常的话,可能需要重启应用程序或者调整应用程序的配置。
  4. 使用工具:使用工具如jstack,jmap,jprofiler等查看线程堆栈信息,确定是否有死循环或者阻塞的线程。
  5. 检查网络状态:如果网络状态不佳,可能导致 CPU 占用过高。
  6. 检查磁盘状态:如果磁盘 IO 过高,可能导致 CPU 占用过高。

JUC

  1. volatile的实现原理?
  2. 讲一讲线程池的工作方式?
  3. 线程池的拒绝策略有哪些?
  1. 保证可见性、有序性,原因可以禁用CPU缓存,直接从主存中读取、使用内存屏障禁止指令重排序
  2. 提交任务到核心线程池,如果核心线程池没满,则创建线程,如果满了判断等待队列线程是否满了,若满了判断最大线程池满没有,如满了则执行拒绝策略。
  3. 拒绝策略一共有四种、直接抛弃不报异常、报异常直接抛弃、抛弃等待队列里等待最长时间的、使用主线程执行任务