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

33 阅读5分钟

面试官:请简要介绍一下 Java 中的多线程,以及如何创建一个线程?

王铁牛:多线程就是多个线程同时运行呗。创建线程可以通过继承 Thread 类或者实现 Runnable 接口。

面试官:嗯,回答得还算清晰。那线程池有什么作用,如何创建一个线程池?

王铁牛:线程池能复用线程,提高效率。创建线程池可以用 Executors 类的方法。

面试官:还不错。再说说 HashMap 的底层实现原理。

王铁牛:它是数组加链表,还有红黑树。

第一轮结束。

面试官:那 ArrayList 呢,它的优缺点是什么?

王铁牛:优点是查询快,缺点是增删慢。

面试官:Spring 框架的核心特性有哪些?

王铁牛:依赖注入,面向切面编程。

面试官:说说 Spring Boot 自动配置的原理。

王铁牛:这个嘛,大概就是自动帮我们配置一些东西吧。

第二轮结束。

面试官:MyBatis 的缓存机制是怎样的?

王铁牛:有一级缓存和二级缓存。

面试官:Dubbo 服务调用的流程是什么?

王铁牛:不太清楚,瞎猜一个,先注册,再调用。

面试官:RabbitMq 如何保证消息的可靠性?

王铁牛:这个……不太会。

第三轮结束。

面试官:今天的面试就到这里,回去等通知吧。

答案:

  1. 多线程及创建线程:多线程是指程序中包含多个执行单元,它们可以并发执行。在 Java 中创建线程有两种常见方式。继承 Thread 类,重写 run 方法,然后通过实例化该类并调用 start 方法来启动线程。例如:
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程执行");
    }
}
MyThread thread = new MyThread();
thread.start();

实现 Runnable 接口,实现其 run 方法,然后将实现类实例作为参数传递给 Thread 类的构造函数来创建线程。例如:

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("线程执行");
    }
}
Thread thread = new Thread(new MyRunnable());
thread.start();
  1. 线程池:线程池的作用是复用线程,避免频繁创建和销毁线程带来的开销,提高系统性能。创建线程池可以使用 Executors 类的方法,如:
ExecutorService executorService = Executors.newFixedThreadPool(5);

这里创建了一个固定大小为 5 的线程池。也可以使用其他方法创建不同类型的线程池,如单线程池、缓存线程池等。 3. HashMap 底层实现原理:HashMap 底层是数组 + 链表 + 红黑树的结构。当往 HashMap 中插入元素时,首先根据 key 的 hash 值计算出在数组中的索引位置。如果该位置为空,则直接插入新节点。如果不为空,则会遍历链表或红黑树,若 key 已存在,则更新对应节点的值;若不存在,则插入新节点。当链表长度达到一定阈值(默认为 8)且数组长度大于等于 64 时,链表会转换为红黑树,以提高查询效率。 4. ArrayList 优缺点:优点是查询效率高,因为它基于数组实现,可以通过下标直接定位元素。缺点是增删操作效率低,因为增删元素时可能需要移动大量元素。例如插入元素时,需要将插入位置及之后的元素向后移动一位。 5. Spring 框架核心特性:依赖注入(DI),它允许将对象之间的依赖关系通过配置的方式注入,而不是在对象内部直接创建依赖对象,这样提高了代码的可维护性和可测试性。面向切面编程(AOP),它允许将一些横切关注点(如日志、事务管理等)与业务逻辑分离,以提高代码的模块化和复用性。 6. Spring Boot 自动配置原理:Spring Boot 利用条件注解(如 @Conditional 系列注解)来实现自动配置。它会根据项目的依赖、配置文件等信息,自动判断需要配置哪些组件和功能。例如,如果项目中引入了数据库相关依赖,Spring Boot 会自动配置数据源等相关组件。通过大量的自动配置类,Spring Boot 能够在默认情况下为开发者提供一个可用的应用程序框架,开发者只需要进行少量的自定义配置即可。 7. MyBatis 缓存机制:MyBatis 有一级缓存和二级缓存。一级缓存是 SqlSession 级别的缓存,在同一个 SqlSession 中,当执行相同的 SQL 语句时,会直接从缓存中获取结果,而不会再次查询数据库。二级缓存是基于 namespace 级别的缓存,多个 SqlSession 可以共享二级缓存。开启二级缓存后,当一个 SqlSession 查询到数据并关闭后,数据会被放入二级缓存中,其他 SqlSession 再次查询相同数据时可以从二级缓存获取。 8. Dubbo 服务调用流程:服务提供者将服务接口和实现类发布到注册中心,注册中心存储了服务的元数据信息。服务消费者从注册中心获取服务提供者的地址等信息,然后通过网络远程调用服务提供者的服务。在调用过程中,Dubbo 会进行远程通信、序列化、反序列化等操作,确保服务调用的顺利进行。 9. RabbitMq 保证消息可靠性:生产者发送消息时,可以设置消息的持久化,确保消息存储到磁盘,即使 RabbitMq 重启也不会丢失。在消费者端,可以采用手动确认模式,确保消费者正确处理完消息后再向 RabbitMq 发送确认,避免消息丢失。RabbitMq 本身也有持久化队列和交换器的机制,保证消息在队列和交换器层面的可靠性。