面试官:请简要介绍一下 Java 中的多线程。
王铁牛:多线程就是一个程序里可以同时运行多个线程呗。
面试官:那线程池的作用是什么?
王铁牛:能复用线程,提高性能,减少创建和销毁线程的开销。
面试官:在高并发场景下,如何合理配置线程池参数?
王铁牛:呃,这个得根据任务类型和系统负载来调吧,我不太确定具体怎么弄。
第一轮提问结束。
面试官:说说 HashMap 的底层实现原理。
王铁牛:它是基于数组和链表实现的,还有红黑树,用来提高查找效率。
面试官:当 HashMap 发生哈希冲突时,会怎么处理?
王铁牛:会形成链表或者红黑树来存储冲突的元素。
面试官:如何优化 HashMap 的性能?
王铁牛:这个,我觉得可以调大初始容量啥的,具体不太清楚。
第二轮提问结束。
面试官:讲讲 Spring 的核心特性。
王铁牛:依赖注入、面向切面编程这些吧。
面试官:Spring Boot 自动配置的原理是什么?
王铁牛:不太明白,好像是根据一些条件自动配置一些组件。
面试官:如何在 Spring Boot 中集成 MyBatis?
王铁牛:呃,得加依赖,配置 XML 文件,好像是这样,具体细节记不清了。
第三轮提问结束。
面试官:今天的面试就到这里,我们会在一周内通知你面试结果,请回家耐心等待。
答案:
- 多线程:多线程是指在一个程序中可以同时运行多个线程。每个线程都有自己独立的执行路径,可以并发执行任务,从而提高程序的执行效率和响应速度。多线程可以通过继承 Thread 类或实现 Runnable 接口来创建,使用 start() 方法启动线程。线程之间可以通过共享内存、使用同步机制(如 synchronized 关键字)来协调访问共享资源,避免数据竞争和不一致问题。同时,还可以使用线程池来管理和复用线程,提高线程的创建和销毁效率。
- 线程池:线程池的作用主要有以下几点:
- 复用线程:避免频繁创建和销毁线程,减少系统开销。
- 提高性能:线程池中的线程可以被重复使用,快速响应任务请求。
- 便于管理:可以统一管理线程资源,设置线程的最大数量、核心线程数、队列容量等参数,以适应不同的业务场景。
- 控制并发度:通过控制线程池中的线程数量,避免过多线程同时执行导致系统资源耗尽或性能下降。
- HashMap 底层实现原理:
- 数组 + 链表/红黑树:HashMap 内部维护一个数组,数组的每个元素是一个链表节点(JDK 1.8 之前)或红黑树节点(JDK 1.8 及之后)。
- 哈希函数:通过对 key 进行哈希计算,得到一个哈希值,然后根据哈希值确定元素在数组中的位置。
- 哈希冲突处理:当两个或多个 key 的哈希值相同,就会发生哈希冲突。在 JDK 1.8 之前,冲突的元素会形成链表,新元素添加到链表头部;在 JDK 1.8 及之后,当链表长度超过 8 且数组容量大于等于 64 时,链表会转换为红黑树,以提高查找效率。
- 扩容机制:当 HashMap 中的元素数量超过数组容量 * 负载因子(默认 0.75)时,会进行扩容。扩容时,会创建一个新的更大的数组,将原数组中的元素重新计算哈希值后放入新数组中。
- Spring 核心特性:
- 依赖注入(Dependency Injection):通过控制反转(IoC)容器,将对象之间的依赖关系由程序代码直接控制转换为由容器来管理。容器根据配置文件或注解,将依赖对象注入到需要的地方,降低了对象之间的耦合度。
- 面向切面编程(Aspect Oriented Programming,AOP):允许将一些通用的功能(如日志记录、事务管理等)从业务逻辑中分离出来,以切面的形式进行统一处理。通过 AOP,可以在不修改原有业务代码的情况下,增强系统的功能和可维护性。
- IoC 容器:负责创建、管理和装配对象,维护对象之间的依赖关系。常见的 IoC 容器实现有 Spring 容器,它通过 XML 配置文件、Java 配置类或注解来定义对象的创建和依赖关系。
- 事务管理:Spring 提供了强大的事务管理功能,支持声明式事务和编程式事务。声明式事务通过注解或 XML 配置,方便地将业务方法纳入事务管理,使得事务处理与业务逻辑分离,提高了代码的可读性和可维护性。
- Spring Boot 自动配置原理:
- 条件配置:Spring Boot 根据项目中引入的依赖和配置信息,自动判断应用的环境和需求。通过一系列的条件注解(如 @ConditionalOnClass、@ConditionalOnMissingBean 等),来决定是否配置某个组件或功能。
- 自动配置类:Spring Boot 提供了大量的自动配置类,这些类定义了各种组件的默认配置。当应用启动时,Spring 会根据条件判断,自动加载符合条件的自动配置类,并将相关的 Bean 注册到容器中。
- 属性绑定:自动配置类会读取 application.properties 或 application.yml 中的配置属性,并将其绑定到相应的组件或配置对象上。这样,开发者可以通过修改配置文件来定制应用的行为,而不需要修改大量的代码。
- 约定大于配置:Spring Boot 遵循约定大于配置的原则,通过默认的配置和约定,减少了开发者的配置工作量,使得应用的开发和部署更加简单快捷。
- 在 Spring Boot 中集成 MyBatis:
- 添加依赖:在项目的 pom.xml 文件中添加 MyBatis 和 MyBatis Spring Boot Starter 的依赖。
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>最新版本</version> </dependency>- 配置数据源:在 application.properties 或 application.yml 中配置数据库连接信息,如数据库驱动、URL、用户名、密码等。
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/yourdb spring.datasource.username=root spring.datasource.password=password- 配置 MyBatis:创建 MyBatis 的配置类,在类上使用 @MapperScan 注解扫描 Mapper 接口所在的包。
import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Configuration; @Configuration @MapperScan("com.example.mapper") public class MyBatisConfig { }- 编写 Mapper 接口和 XML 文件:创建 Mapper 接口,定义数据库操作方法,并编写对应的 XML 文件,实现 SQL 语句。
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; @Mapper public interface UserMapper { @Select("SELECT * FROM user WHERE id = #{id}") User getUserById(Integer id); }- 使用 Mapper:在 Service 或其他需要的地方注入 Mapper 接口,调用接口方法进行数据库操作。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserService { @Autowired private UserMapper userMapper; public User getUserById(Integer id) { return userMapper.getUserById(id); } }
通过以上步骤,就可以在 Spring Boot 项目中集成 MyBatis,实现数据库操作。