面试题day26

用友

2021年9月1日Java一面

  • Java有哪些集合,以及他们有哪些实现?

    list map set

    arraylist linkedlist hashmap treemap hashset treeset

  • HashMap底层实现,扩容了解吗?

    • 扰动函数
      • (h = key.hashCode()) ^ (h >>> 16); 低16位与高16位做异或操作^,减少hash碰撞
    • 扩容
      • 链表引发
        • 链表长度大于8,判断是否转为红黑树
          • 数组大小大于64,转红黑树
          • 数组大小小于64,扩容
      • 数组引发
        • 数组元素大于容量与扩容因子之积,扩容
      • 过程
        • 每次扩容时都是将容量翻倍,即创建一个2倍大的新数组,然后再将旧数组中的数组迁移到新数组里。由于HashMap中数组的容量为2^N,所以可以用位移运算计算新容量,效率很高。在数据迁移时,为了兼顾性能,不会重新计算一遍每个key的哈希值,而是根据位移运算后(左移翻倍)多出来的最高位来决定,如果高位为0则元素位置不变,如果高位为1则元素的位置是在原位置基础上加上旧的容量。
  • 说一说ConcurrentHashMap

    • 通过部分锁定+CAS算法来进行实现线程安全的
    • put
      • 先计算哈希值
      • 再确定map是否初始化
      • 插入数据
        • 数组插入,cas
        • 链表插入,先扩容,加锁
    • 扩容
      • 1.7
        • 扩容时,对待扩容Segment内部会进行扩容,不影响其他Segment对象
        • 扩容时,先生成新的数组,然后转移元素到新数组中
        • 扩容的判断也是每个Segment内部单独判断的,判断是否超过阈值
      • 1.8
        • 如果某个线程put时,发现没有正在进行扩容,那么该线程一起进行扩容
        • 如果某个线程put时,发现没有正在进行扩容,则将key-value添加到ConcurrentHashMap中, 然后判断是否超过阈值,超过了则进行扩容
        • ConcurrentHashMap是支持多个线程同时扩容的。扩容前也是生成一个新数组,在转移元素时,先将原数组分组,将每组分给不同的线程来进行元素的转移,每个线程负责一组或多组的元素转移工作
  • synchronized加静态方法和成员方法上有什么区别?

    锁对象不同

    • 加锁方式
      • 同步代码块(monitorenter和monitorexit)
      • 同步方法(ACC_SYNCHRONIZED)
    • 操作流程
      • 首先会进入 EntryList 集合,当线程获取到对象的monitor后,进入 _Owner区域并把monitor中的owner变量设置为当前线程,同时monitor中的计数器count加1;
      • 若线程调用 wait() 方法,将释放当前持有的monitor,owner变量恢复为null,count自减1,同时该线程进入 WaitSet集合中等待被唤醒;
      • 若当前线程执行完毕,也将释放monitor(锁)并复位count的值,以便其他线程进入获取monitor(锁);
    • 锁升级
    • 锁消除
      • Java虚拟机通过对运行上下文的扫描,经过逃逸分析,去除不可能存在竞争的锁,通过这种方式消除没有必要的锁,可以节省毫无意义的请求锁时间。实质是JIT编译器的同步省略或者叫同步消除
    • 锁粗化
      • 按理来说,同步块的作用范围应该尽可能小,但是加锁解锁也需要消耗资源,如果存在一系列的连续加锁解锁操作,可能会导致不必要的性能损耗。锁粗化就是将多个连续的加锁、解锁操作连接在一起,扩展成一个范围更大的锁,避免频繁的加锁解锁操作。
    • 自适应自旋锁
      • 如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程正在运行中,那么虚拟机就会认为这次自旋也很有可能再次成功,进而允许自旋等待持续相对更长的时间。另一方面,如果对于某个锁,自旋很少成功获得过锁,那在以后要获取这个锁时将有可能直接省略掉自旋过程,以避免浪费处理器资源
  • sleep()和wait()有什么区别?

    类、时机、释放锁

    超时等待状态、等待状态

  • 比如说有两个线程,有一个线程走到了synchronized方法里面了,另一个线程也掉入了这个synchronized方法,那么线程会怎么样?

    锁碰撞、线程阻塞

  • 线程池有哪些类型?

    单线程池、定量线程池、动态线程池、定期线程池

  • 如果线程池的线程满了的话,再往里面塞任务,会怎么做?它会再往哪个位置去存放这些东西?或者做一些其他处理?有什么一些策略?

    核心线程数、阻塞队列、最大线程数、拒绝策略

    直接抛出、抛出最早、抛异常(默认)、调用者执行

    cpu密集型 n+1 io密集型 2n

  • CAS是什么概念?

    原子操作、将预期值与旧值比较,成功更新为新值

    aba问题、内存消耗、原子性

  • MySQL常用存储引擎

    innodb、myisam

    事务、锁、mvcc、外键、数据存储

  • 事务隔离级别

    ru rc rr s

    脏读、不可重复读、幻读

  • 如果要存放金额等带精度的数据,使用什么字段类型?

    BigDecimal

  • 分页用什么关键词?

    SELECT * from user limit #{start},#{pageSize}
    
  • 索引类型有哪些?

    hash 数组 b+树

    遍历层级短 io效率高

  • 有没有看到过组合索引?

  • 使用where时哪些语法尽量不要用?

    索引失效

  • 最左优先原则说一说

  • mybatis里面#{}与${}的区别,怎么理解预编译?为什么执行sql时要生成一个带?的sql?

    预编译,提前占位

  • 有没有看过框架的源码?

    springmvc springboot

  • 接触过哪些算法?

    排序算法、搜索算法

  • Java内存管理

    方法区 堆

    直接内存 虚拟机栈 本地方法栈 程序计数器

    清除 复制 压缩

    分代假说

    可达性算法 引用计数法

    静态变量 常量 虚拟机栈 本地方法栈

  • redis有了解过吗?

    • redis的五大基本数据类型

      • string 缓存 session共享 分布式锁
      • list 消息队列
      • hash 存储对象
      • set 集合
      • zset 排行榜
    • redis的两种持久化方式,redis的默认持久化方式

      • aof 命令
      • rdb 快照 默认
    • redis中的删除策略

      • 定时删除
        • 创建一个定时器,当key有过期时间时,时间一到,定时器任务就会立即执行 将expires区域和k-v区域都删除
        • 优点:节约内存
        • 缺点:cpu压力较大,此时无论cpu负载量多高,都会占用cpu来释放,影响redis的吞吐量
      • 惰性删除
        • 数据过期后,并不会立刻删除 等到该数据下次访问的时候,redis才会删除该数据,并返回该值为nil
        • 优点:节省cpu的资源
        • 缺点:可能存在大量的,无人访问的数据会一直存在服务器
      • 定期删除
        • 每秒钟定期对redis中每个库的数据进行轮询 轮询的数据,对过期的数据随机删除一部分 如果随机删除的数据占轮训数据的比例超过一定值,继续轮询删除
  • 微服务有接触过吗?

  • springboot和springMVC区别

    配置

posted @ 2022-08-11 21:24  Faetbwac  阅读(36)  评论(0编辑  收藏  举报