互联网大厂Java面试大揭秘:核心知识深度考察
面试官:请简要介绍一下Java中的多线程,以及如何创建一个线程?
王铁牛:Java中的多线程是指程序中包含多个执行单元,这些执行单元可以并发执行。创建线程可以通过继承Thread类或者实现Runnable接口来实现。
面试官:回答得不错。那请说一下线程池的作用和优点。
王铁牛:线程池的作用是管理线程,避免频繁创建和销毁线程,提高性能。优点是可以提高响应速度、降低资源消耗、便于线程管理。
面试官:很好。再问一个问题,HashMap在多线程环境下会有什么问题?
王铁牛:HashMap在多线程环境下会出现死循环、数据丢失等问题。因为它不是线程安全的。
第一轮结束,王铁牛对于简单问题回答得较为流畅,得到了面试官的夸赞。
面试官:接下来问一些关于JVM的问题。请简述一下JVM的内存结构。
王铁牛:JVM的内存结构包括堆、栈、方法区等。堆是存放对象实例的地方,栈是存放局部变量等,方法区存放类信息等。
面试官:那类加载机制的过程是怎样的?
王铁牛:类加载机制包括加载、验证、准备、解析、初始化五个过程。
面试官:请说一下垃圾回收算法有哪些?
王铁牛:垃圾回收算法有标记清除算法、标记整理算法、复制算法、分代收集算法等。
第二轮结束,王铁牛对JVM相关问题回答得有好有坏,部分回答不够清晰。
面试官:最后一轮,问一些关于框架的问题。Spring框架的核心特性是什么?
王铁牛:Spring框架的核心特性包括依赖注入、面向切面编程、IoC容器等。
面试官:那Spring Boot的优势在哪里?
王铁牛:Spring Boot的优势是简化配置、快速搭建项目、内置Tomcat等。
面试官:请简述一下MyBatis的工作原理。
王铁牛:MyBatis通过XML或注解配置SQL语句,然后通过SqlSessionFactory创建SqlSession,执行SQL操作。
面试结束,面试官表示会让王铁牛回家等通知。整体来看,王铁牛在面试中对一些简单问题回答较好,但对于复杂问题的回答存在不足,需要进一步提升对Java核心知识、框架等的理解和掌握程度。
答案详解
多线程:
- 创建线程方式:
- 继承Thread类:创建一个类继承Thread类,重写run方法,然后创建该类的实例并调用start方法启动线程。例如:
class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程执行");
}
}
MyThread thread = new MyThread();
thread.start();
- 实现Runnable接口:创建一个类实现Runnable接口,重写run方法,然后创建Thread类的实例并传入该实现类的实例,调用start方法启动线程。例如:
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("线程执行");
}
}
Thread thread = new Thread(new MyRunnable());
thread.start();
线程池:
- 作用:管理线程,避免频繁创建和销毁线程,提高性能。
- 优点:
- 提高响应速度:因为线程已经存在,无需等待创建线程的时间。
- 降低资源消耗:减少线程创建和销毁的开销。
- 便于线程管理:可以控制线程的数量、线程的生命周期等。
HashMap在多线程环境:
- 问题:
- 死循环:在扩容时可能会导致链表形成环形结构,从而在遍历或插入时陷入死循环。
- 数据丢失:在多线程同时进行put操作时,可能会覆盖其他线程插入的数据。
- 原因:HashMap内部结构是数组+链表(JDK8后引入红黑树),在多线程操作时,扩容和插入等操作可能会导致数据不一致。
JVM内存结构:
- 堆:存放对象实例,是JVM管理的最大一块内存区域,被所有线程共享。
- 栈:存放局部变量、方法调用等信息,每个线程都有自己独立的栈空间。
- 方法区:存放类信息、常量、静态变量等,被所有线程共享。
类加载机制:
- 加载:将类的字节码文件加载到内存中,生成Class对象。
- 验证:检查加载的字节码文件是否符合JVM规范,确保安全。
- 准备:为类的静态变量分配内存,并设置默认初始值。
- 解析:将符号引用替换为直接引用。
- 初始化:执行类的静态代码块和静态变量的赋值操作。
垃圾回收算法:
- 标记清除算法:先标记出所有需要回收的对象,然后统一回收。缺点是会产生内存碎片。
- 标记整理算法:标记出可回收对象后,将存活对象向一端移动,然后清理边界以外的内存。
- 复制算法:将内存分为两块,每次只使用其中一块,当一块内存使用完后,将存活对象复制到另一块,然后清理原来的内存。适用于对象存活率低的情况。
- 分代收集算法:根据对象的存活周期将内存分为不同的区域,不同区域采用不同的垃圾回收算法,如新生代采用复制算法,老年代采用标记清除或标记整理算法。
Spring框架核心特性:
- 依赖注入:通过IoC容器将对象之间的依赖关系进行管理和注入,降低对象之间的耦合度。
- 面向切面编程:可以将横切关注点(如日志、事务等)与业务逻辑分离,提高代码的可维护性和复用性。
- IoC容器:负责创建、配置和管理对象,通过配置文件或注解等方式实现对象的依赖注入和生命周期管理。
Spring Boot优势:
- 简化配置:采用自动配置原理,减少了大量的XML或Java配置代码。
- 快速搭建项目:提供了各种starter依赖,快速集成各种功能。
- 内置Tomcat:无需额外配置Tomcat等服务器,直接运行项目。
MyBatis工作原理:
- 通过XML或注解配置SQL语句。
- 通过SqlSessionFactory创建SqlSession,SqlSession是执行SQL操作的主要接口。
- SqlSession通过映射器(Mapper)接口调用对应的SQL语句,映射器接口中的方法名对应XML中的SQL语句的id。
- 执行SQL操作后返回结果,结果可以是单个对象、对象列表等。例如:
<mapper namespace="com.example.mapper.UserMapper">
<select id="getUserById" parameterType="int" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>
</mapper>
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("com.example.mapper.UserMapper.getUserById", 1);
sqlSession.close();