《互联网大厂Java面试核心知识点考察》

48 阅读8分钟

文章标题:《互联网大厂Java面试核心知识点考察》

文章内容: 这是一场互联网大厂的Java求职者面试,面试官一脸严肃,对面坐着求职者王铁牛。

第一轮面试官:先说说Java中ArrayList和HashMap的区别。 王铁牛:ArrayList是有序的,按顺序存储元素,HashMap是无序的,通过键值对存储。 面试官:嗯,回答得不错。那HashMap在多线程环境下会有什么问题? 王铁牛:好像会数据错乱啥的,具体不太清楚。 面试官:那ArrayList在多线程环境下如何保证线程安全? 王铁牛:可以用Collections.synchronizedList把它包装一下。 面试官:回答得还行。

第二轮面试官:讲讲Spring的IOC是什么? 王铁牛:IOC就是控制反转,把对象的创建和管理交给Spring容器。 面试官:不错。那Spring Boot相对于Spring有什么优势? 王铁牛:好像配置更简单,能快速搭建项目,具体也说不太清。 面试官:Spring Boot的自动配置原理能讲讲吗? 王铁牛:呃,就是根据一些条件自动配置一些组件吧,细节不太熟。

第三轮面试官:MyBatis的一级缓存和二级缓存了解吗? 王铁牛:一级缓存是SqlSession级别的,二级缓存是namespace级别的。 面试官:还行。Dubbo的服务治理有哪些方面? 王铁牛:好像有负载均衡、服务降级啥的,具体不太会说。 面试官:RabbitMQ的消息确认机制是怎样的? 王铁牛:不太清楚,就知道有个确认机制。 面试官:最后问个,xxl - job的核心原理是什么? 王铁牛:这个不太了解。

面试官思索片刻后说道:“今天的面试就到这里,你回去等通知吧。我们会综合评估所有候选人,之后会通过邮件或者电话的形式告知你结果。感谢你今天来参加面试,希望你之后能继续提升自己的技术能力,对一些技术点理解得更深入透彻些,无论是基础的集合类,还是框架相关的原理,都需要有更清晰的认知,这样在实际项目中才能更好地运用。”

答案:

  1. ArrayList和HashMap的区别
    • 存储结构:ArrayList是基于数组实现的,有序存储元素,元素可以重复;HashMap是基于哈希表实现的,以键值对形式存储,键不能重复,无序存储。
    • 数据访问:ArrayList通过索引访问元素,时间复杂度为O(1);HashMap通过键获取值,理想情况下时间复杂度为O(1),但在哈希冲突严重时,时间复杂度会退化。
    • 应用场景:ArrayList适合需要按顺序访问元素,且元素数量可动态增长的场景;HashMap适合根据键快速查找值的场景。
  2. HashMap在多线程环境下的问题
    • 数据错乱:在多线程环境下,当多个线程同时对HashMap进行put操作时,可能会导致哈希表的结构被破坏,出现数据错乱,比如链表成环等问题,这会导致在获取元素时出现死循环等严重错误。
    • 丢失数据:多线程同时put时,可能会出现覆盖数据的情况,导致数据丢失。
  3. ArrayList在多线程环境下保证线程安全的方法
    • 使用Collections.synchronizedList:通过调用Collections.synchronizedList(new ArrayList<>())方法,返回一个线程安全的List,它内部通过同步锁来保证对List的操作是线程安全的。
    • 使用CopyOnWriteArrayList:写操作时会复制一份新的数组,在新数组上进行操作,操作完成后再将新数组赋值给原数组,读操作直接读取原数组,这样读操作和写操作可以并发进行,但写操作开销较大。
  4. Spring的IOC(控制反转)
    • 概念:IOC是一种设计思想,将对象的创建和管理从应用程序代码中转移到Spring容器中。在传统编程中,对象的创建和依赖关系由开发者在代码中手动管理,而IOC通过容器来负责这些工作。
    • 实现方式:主要通过依赖注入(DI)来实现,包括构造函数注入、Setter方法注入和接口注入等方式。例如,一个类A依赖类B,在IOC容器中,可以通过配置将B的实例注入到A中,而不是在A类内部手动创建B的实例。
  5. Spring Boot相对于Spring的优势
    • 快速搭建项目:Spring Boot提供了大量的starter依赖,通过引入相关的starter,能快速搭建一个基于Spring的项目,减少了大量的配置工作。例如,引入spring - boot - starter - web就可以快速搭建一个Web项目。
    • 自动配置:Spring Boot能根据项目的依赖自动配置Spring应用,开发者无需手动配置大量的Bean。比如,引入spring - boot - starter - jdbc和数据库驱动依赖后,Spring Boot会自动配置数据源、JdbcTemplate等相关组件。
    • 生产级别的监控:Spring Boot Actuator提供了生产环境下的监控功能,如查看应用的健康状态、性能指标等。
  6. Spring Boot的自动配置原理
    • 条件注解:Spring Boot使用了大量的条件注解,如@ConditionalOnClass@ConditionalOnProperty等。当满足特定条件时,才会配置相应的Bean。例如,@ConditionalOnClass表示当类路径下存在某个类时,才会进行配置。
    • 配置类和自动配置类:Spring Boot有许多自动配置类,这些类会根据条件注解来决定是否生效。同时,开发者也可以自定义配置类来覆盖自动配置的内容。
    • Spring Factories机制:在META - INF/spring.factories文件中,定义了自动配置类的全限定名,Spring Boot启动时会加载这些自动配置类,并根据条件进行配置。
  7. MyBatis的一级缓存和二级缓存
    • 一级缓存
      • 作用域:一级缓存是SqlSession级别的缓存,在同一个SqlSession中,执行相同的SQL查询时,MyBatis会先从一级缓存中查找结果,如果存在则直接返回,不再执行SQL语句。
      • 生命周期:当SqlSession关闭时,一级缓存也会被清空。
    • 二级缓存
      • 作用域:二级缓存是namespace级别的缓存,不同的SqlSession之间可以共享二级缓存。当一个SqlSession查询数据时,会先从二级缓存中查找,如果不存在再从数据库查询,查询结果会放入二级缓存。
      • 开启和配置:需要在MyBatis的配置文件中开启二级缓存,并且在Mapper.xml文件中配置<cache>标签来设置缓存的相关属性,如缓存的类型、刷新间隔等。
  8. Dubbo的服务治理
    • 服务注册与发现:Dubbo使用注册中心(如Zookeeper、Nacos等)来注册和发现服务。服务提供者将自己的服务注册到注册中心,服务消费者从注册中心获取服务提供者的地址信息,从而实现服务调用。
    • 负载均衡:当有多个服务提供者提供相同的服务时,Dubbo提供了多种负载均衡策略,如随机、轮询、最少活跃调用数等,以合理分配请求到不同的服务提供者。
    • 服务降级:当某个服务出现故障或响应时间过长时,为了保证整体系统的可用性,Dubbo可以进行服务降级,返回一个默认值或者执行一个备用逻辑,避免级联故障。
    • 服务限流:为了防止某个服务被过度调用,Dubbo可以设置限流规则,限制单位时间内的请求次数,保护服务不被压垮。
  9. RabbitMQ的消息确认机制
    • 生产者确认(Publisher Confirm)
      • 开启方式:通过设置channel.confirmSelect()开启。
      • 原理:当生产者发送消息到RabbitMQ后,RabbitMQ会给生产者发送一个确认消息,告知生产者消息是否成功到达服务器。如果消息成功到达,生产者会收到一个ACK确认;如果消息未成功到达,生产者会收到一个NACK确认。生产者可以通过addConfirmListener方法来监听ACK和NACK消息,进行相应的处理,比如重发消息。
    • 消费者确认(Consumer Ack)
      • 开启方式:默认情况下,消费者确认是自动确认的,即消费者接收到消息后,RabbitMQ就认为消息已被成功处理。也可以设置为手动确认,通过设置autoAck = false,然后在消费者处理完消息后,调用channel.basicAck方法手动确认消息,这样可以确保消息不会因为消费者处理过程中出现异常而丢失。如果消费者在处理消息时出现异常,没有调用basicAck,RabbitMQ会将消息重新放入队列,重新分发给其他消费者。
  10. xxl - job的核心原理
  • 调度中心:xxl - job有一个调度中心,负责管理调度任务,包括任务的新增、修改、删除、暂停、恢复等操作。调度中心基于Quartz实现定时调度,通过数据库存储任务信息和调度日志。
  • 执行器:任务的具体执行者,与调度中心进行通信。执行器启动时会向调度中心注册自己,调度中心根据任务配置,定时触发任务,并将任务发送给对应的执行器。执行器接收到任务后,执行具体的业务逻辑,并将执行结果返回给调度中心。
  • 通信协议:调度中心和执行器之间通过HTTP协议进行通信,传输任务信息和执行结果等数据。