面试官:第一轮提问开始。首先,讲讲Java中的多线程如何实现资源共享?
王铁牛:呃,就是用那个synchronized关键字吧,好像是能保证同一时间只有一个线程访问共享资源。
面试官:回答正确。那线程池的核心参数都有哪些,分别有什么作用?
王铁牛:corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、threadFactory、handler。corePoolSize是核心线程数,maximumPoolSize是最大线程数,keepAliveTime是线程池中的线程在超出corePoolSize后,多余的空闲线程的存活时间,unit是keepAliveTime的时间单位,workQueue是任务队列,threadFactory是线程工厂,handler是拒绝策略。
面试官:不错,回答得挺清晰。最后一个问题,HashMap在多线程环境下会出现什么问题?
王铁牛:嗯……会出现死循环吧,好像是扩容的时候会出问题。
面试官:好,第一轮提问结束。接下来是第二轮提问。说说JVM的内存结构。
王铁牛:有堆、栈、方法区,还有本地方法栈、程序计数器。堆是存放对象实例的地方,栈是存放局部变量、方法调用等,方法区存类信息、常量、静态变量等。
面试官:那类加载机制有哪些?
王铁牛:嗯……有加载、验证、准备、解析、初始化。
面试官:准备阶段主要做什么?
王铁牛:呃,就是为类的静态变量分配内存并设置默认初始值。
面试官:第二轮提问完毕。现在进入第三轮提问。Spring的核心特性有哪些?
王铁牛:依赖注入、面向切面编程、IoC容器。
面试官:Spring Boot的自动配置原理是什么?
王铁牛:好像是通过条件注解来自动配置一些Bean。
面试官:最后一个问题,MyBatis的缓存机制是怎样的?
王铁牛:有一级缓存和二级缓存,一级缓存是SqlSession级别的,二级缓存是namespace级别的。
面试官:好,三轮提问都结束了。回家等通知吧。
答案:
- 多线程实现资源共享:synchronized关键字可以保证同一时间只有一个线程访问共享资源。它可以修饰代码块或者方法,当一个线程访问被synchronized修饰的代码块或方法时,其他线程需要等待该线程释放锁后才能访问。
- 线程池核心参数:
- corePoolSize:核心线程数,当提交的任务数小于corePoolSize时,线程池会创建新的线程来执行任务。
- maximumPoolSize:最大线程数,当提交的任务数大于corePoolSize且任务队列已满时,线程池会创建新的线程,直到线程数达到maximumPoolSize。
- keepAliveTime:线程池中的线程在超出corePoolSize后,多余的空闲线程的存活时间。
- unit:keepAliveTime的时间单位。
- workQueue:任务队列,用于存放提交的任务,当线程池中的线程数小于corePoolSize时,新提交的任务会放入workQueue中。
- threadFactory:线程工厂,用于创建线程。
- handler:拒绝策略,当提交的任务数大于maximumPoolSize且任务队列已满时,会调用handler来处理新提交的任务。
- HashMap在多线程环境下的问题:在多线程环境下,HashMap在扩容时可能会出现死循环问题。这是因为在扩容时,HashMap会重新计算节点的位置,并且可能会导致链表形成环形结构,从而在获取元素时陷入死循环。
- JVM内存结构:
- 堆:存放对象实例的地方。
- 栈:存放局部变量、方法调用等。
- 方法区:存类信息、常量、静态变量等。
- 本地方法栈:与虚拟机栈类似,用于执行本地方法。
- 程序计数器:记录当前线程执行的字节码指令地址。
- 类加载机制:
- 加载:将类的字节码文件加载到内存中。
- 验证:验证字节码文件的正确性。
- 准备:为类的静态变量分配内存并设置默认初始值。
- 解析:将符号引用转换为直接引用。
- 初始化:执行类的初始化代码,比如静态变量的赋值等。
- Spring的核心特性:
- 依赖注入:通过IoC容器将对象之间的依赖关系注入到对象中。
- 面向切面编程:通过切面来实现横切关注点,比如日志、事务等。
- IoC容器:管理对象的创建、配置和生命周期。
- Spring Boot自动配置原理:Spring Boot通过条件注解来自动配置一些Bean。它会根据应用的依赖和配置,自动猜测并配置合适的Bean。例如,如果应用中引入了数据库相关的依赖,Spring Boot会自动配置数据源等相关的Bean。
- MyBatis缓存机制:
- 一级缓存:是SqlSession级别的缓存,当一个SqlSession执行查询时,会先从一级缓存中查找,如果找到则直接返回结果,避免重复查询数据库。
- 二级缓存:是namespace级别的缓存,多个SqlSession可以共享二级缓存。当一个SqlSession执行查询时,会先从一级缓存中查找,然后再从二级缓存中查找。二级缓存的开启需要在Mapper.xml文件中配置。