《互联网大厂Java求职者面试:核心知识大考验》

31 阅读5分钟

面试官:第一轮面试开始。首先,说说 Java 中的多线程有哪些实现方式?

王铁牛:嗯,这个简单,有继承 Thread 类和实现 Runnable 接口这两种方式。

面试官:不错,回答正确。那线程池的核心参数都有哪些?

王铁牛:有 corePoolSize、maximumPoolSize、keepAliveTime、unit 和 workQueue。

面试官:很好。再问个,HashMap 在 JDK1.8 之后做了哪些优化?

王铁牛:这个嘛……它在链表长度大于 8 且数组长度大于 64 时会将链表转换为红黑树,还有一些其他的,嗯……想不太起来了。

面试官:第二轮面试。讲讲 JVM 的内存模型都包含哪些部分?

王铁牛:有堆、栈、方法区这些。

面试官:Spring 框架中依赖注入有几种方式?

王铁牛:有构造器注入、setter 注入这些。

面试官:MyBatis 的缓存机制了解吗?

王铁牛:不太清楚,瞎答一个,好像有一级缓存和二级缓存吧。

面试官:最后一轮面试。Dubbo 的集群容错策略有哪些?

王铁牛:呃……不太记得全了,好像有 failover、failfast 这些。

面试官:RabbitMq 的消息确认机制是怎样的?

王铁牛:这个真不会,随便说一个吧,应该是发送端确认和接收端确认吧。

面试官:xxl-job 的调度中心是如何实现任务调度的?

王铁牛:完全不懂,乱说一通。

面试官:好了,面试结束,回去等通知吧。

答案

  • Java 多线程实现方式
    • 继承 Thread 类:通过继承 Thread 类并重写 run 方法来创建线程。
    • 实现 Runnable 接口:实现 Runnable 接口的 run 方法,然后将其作为参数传递给 Thread 类的构造函数来创建线程。
  • 线程池核心参数
    • corePoolSize:线程池的核心线程数,当提交的任务数小于 corePoolSize 时,会创建新线程来执行任务。
    • maximumPoolSize:线程池允许的最大线程数,当提交的任务数大于 corePoolSize 且任务队列已满时,会创建新线程来执行任务,直到线程数达到 maximumPoolSize。
    • keepAliveTime:线程池中非核心线程的存活时间,当线程数大于 corePoolSize 时,多余的线程在空闲时间超过 keepAliveTime 后会被销毁。
    • unit:keepAliveTime 的时间单位。
    • workQueue:任务队列,用于存放提交的任务,当提交的任务数大于 corePoolSize 时,会将任务放入任务队列中。
  • HashMap 在 JDK1.8 之后的优化
    • 链表转红黑树:当链表长度大于 8 且数组长度大于 64 时,会将链表转换为红黑树,以提高查询效率。
    • 扩容优化:扩容时会将链表节点按原顺序插入新数组,减少链表反转的开销。
    • 哈希算法改进:采用了扰动函数来增加哈希值的随机性,减少哈希冲突。
  • JVM 内存模型
    • :存放对象实例,是垃圾回收的主要区域。
    • :存放局部变量、方法调用等信息。
    • 方法区:存放类信息、常量、静态变量等。
    • 程序计数器:记录当前线程执行的字节码指令地址。
    • 本地方法栈:为本地方法提供服务。
  • Spring 依赖注入方式
    • 构造器注入:通过构造函数传入依赖对象。
    • setter 注入:通过 setter 方法传入依赖对象。
    • 接口注入:通过实现特定接口来注入依赖对象。
    • 基于注解的注入:如 @Autowired、@Resource 等注解。
  • MyBatis 缓存机制
    • 一级缓存:是 SqlSession 级别的缓存,默认开启。在同一个 SqlSession 中,对相同 SQL 的查询会从缓存中获取数据,不会再次查询数据库。
    • 二级缓存:是基于 namespace 级别的缓存,需要手动开启。多个 SqlSession 可以共享二级缓存,当一个 SqlSession 对数据进行修改时,会刷新二级缓存。
  • Dubbo 集群容错策略
    • failover:失败自动切换,当调用失败时,会自动重试其他服务器。
    • failfast:快速失败,当调用失败时,立即抛出异常,不再重试。
    • failsafe:失败安全,当调用失败时,直接忽略,不抛出异常。
    • failback:失败后自动恢复,当调用失败时,会在后台异步重试。
    • forking:并行调用多个服务器,只要有一个成功就返回。
    • broadcast:广播调用所有服务器,逐个调用,任意一个报错则报错。
  • RabbitMq 消息确认机制
    • 发送端确认
      • 事务机制:通过 channel.txSelect()开启事务,channel.txCommit()提交事务,channel.txRollback()回滚事务。事务机制保证消息发送成功,但性能较低。
      • Confirm 机制:通过 channel.confirmSelect()开启确认模式,发送消息后通过 channel.waitForConfirms()或 channel.waitForConfirmsOrDie()等待服务器确认。Confirm 机制有普通确认和批量确认两种方式。
    • 接收端确认
      • 自动确认:消费者接收到消息后,自动确认消息已被接收。
      • 手动确认:消费者接收到消息后,需要手动调用 channel.basicAck()方法来确认消息已被接收。
  • xxl-job 调度中心实现任务调度的原理
    • 调度中心存储任务信息:包括任务的执行表达式、任务参数等。
    • 定时触发调度:根据任务的执行表达式,调度中心定时触发任务调度。
    • 任务分发:调度中心将任务分发给执行器,执行器负责具体的任务执行。
    • 任务执行监控:调度中心监控任务的执行情况,包括执行结果、执行时间等。
    • 任务重试机制:当任务执行失败时,调度中心会根据配置进行重试。