面试题合集(持续更新中。。。)
1.Redis缓存的删除策略
- 算法
FIFO First in First out 先近先出。删除进入redis最早的key。LRU Least Recently Used 最近最早被使用。删除最近一段时间内,被使用过的使用时间离现在最远的key。
LFU Least Frequently Used 最近最不经常使用。删除最近一段时间内,使用频率最少的key。
- 具体策略,当有新key要写入却空间不足时,redis执行的操作
noeviction 不删除任何key,返回错误信息。allkeys-lru 从所有key中选择最近最早被使用的key删除。
volatile-lru 从设置过有效期的key中选择最近最早被使用的key删除。
allkeys-lfu 从所有key中选择最近最不常使用的key删除。
volatile-lfu 从设置过有效期的key中选择最不常使用的key删除。
volatile-ttl 从设置过有效期的key中选择最快要到期的key删除。
2.Mybatis缓存
- mybatis的一级缓存
一级缓存是SQLSession级别的缓存。当执行过一次查询操作之后,会在SQLSession中设置缓存,当执行下一次查询,且查询sql及所有参数完全一致时,会直接从一级缓存中获取数据,而不是再次去执行数据库查询。当数据库有commit操作时(Insert,update,delete操作)会完全清除一级缓存。
二级缓存是Mapper级别的缓存。
二级缓存有总开关和分开关。总开关在mybatis配置中设置。分开关在mapper.xml文件中配置。默认是不开启的。
二级缓存开启时,数据查询时会从二级缓存中先取,未取到回去一级缓存中取,最后去数据库中取。
3.springboot启动流程
- 创建SpringApplication实例
- 1.1 判断是否为web环境- 1.2 设置初始化器:从META-INF/spring.factory处读取key为org.springframework.context.ApplicationContextInitializer的value,并进行实例化
- 1.3 设置监听器
- 1.4 推断应用入口
- 执行SpringApplication.run()
- 2.1 获取SpringApplicationRunListener,启动监听- 2.2 根据SpringApplicationRunListener以及参数来准备环境
- 2.3 创建ApplicationContext(spring上下文)
- 2.4 创建FailureAnalyzer,用于触发spring.factory加载的failureAnalyzer和FailureAnalysisReporter实例
- 2.5 spring上下文前置配置
- 2.6 spring上下文刷新
- 2.7 spring上下文后置处理
4.Spring的Bean是否为单例?线程是否安全?
spring的bean有单例,但并不只是单例,有几种作用域:- 4.1 singleton:单例。是默认作用域。
- 4.2 prototype:原型。在使用的时候每次都会创建一个新对象。
- 4.3 request:请求。每次http请求是创建一个新对象。适用于WebApplicationContext环境下。
- 4.4 session:会话。同一个会话使用同一个实例(不同会话使用不同实例)。
- 4.5 global-session:全局会员。所有会话共享一个示例。
原型Bean,在每次使用的时候都需要新建一个对象,不存在多线程问题,所以是线程安全的。
单例Bean,是被所有线程共享的。如果是无状态的单例Bean(比如spring中的Dao,Service,Controller等,用@AutoWired,@Resource等注解注入的)就是线程安全的。只注重方法。如果是有状态的单例Bean(比如spring官方提供的Bean)则是有Spring官方提供了ThreadLocal去解决线程安全问题。
5.Java中是否存在内存泄露?举例?
- Java中是存在内存泄露的
- 示例
pubilc void test(){ Person p1 = new Person();
Person p2 = new Person();
p1 = p2;
}
这么写的话,p1和p2,除了互相依赖,并没有实质性的操作,按理说应该被GC回收,但当GC执行的时候,会发现p1和p2两个对象是一直占用的,并不能被回收。其实就已经是内存泄露了。
6 JVM内存模型
- 6.1 堆内存(Heap)虚拟机启动是创建,是虚拟机中占用内存最大的一块,被该进程中所有线程所共享。此内存的唯一作用就是存放对象实例,几乎所有的对象都是在堆中完成内存分配。
堆可以分为老年代和新生代。
老年代和新生代的比例为2:1,可通过 `–XX:NewRatio` 参数来指定。
新生代又分为Eden区,from和to区。Eden:from:to = 8:1:1,可通过`–XX:SurvivorRatio`参数来指定。
- 6.2 方法区(Method Area)
也称为永久代。用于存放虚拟机加载的类信息、常量、静态变量、是各个线程共享的内存区域。
JDK8之后,取消了永久代,可以将永久代称为元数据区(MetaSpace)。
以下为方法区配置:
-XX:PermSize=64MB 最小尺寸,初始分配-XX:MaxPermSize=256MB 最大允许分配尺寸,按需分配
XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled 设置垃圾不回收
默认大小
-server选项下默认MaxPermSize为64m
-client选项下默认MaxPermSize为32m
- 6.3 虚拟机栈(JVM Stack)是java方法执行时的内存模型。每个方法执行时都会创建一个栈帧,用于存储局部变量表(包括参数),操作栈,方法出口等信息。每个方法从被调用到执行完,就是一个栈帧在虚拟机中从入栈到出栈的过程。
所有参数,操作,返回值等在栈中的操作过程可以叫做压栈。先进入栈帧的会在栈最底部,后进入的会在最顶部。出栈的时候,会从顶部开始出,也就是所谓的先进后出,后进先出。
- 6.4 本地方法栈(Native Method Stack)
这块区域与虚拟机栈类似,只是虚拟机栈是为虚拟机中执行的Java方法服务的,而本地方法栈是为虚拟机中用到的Native方法服务的。
- 6.5 程序计数器(PC Register)
用于表示当前线程执行的字节码文件的行号指示器。
不被线程共享,多线程操作时,每个线程都有自己独立的程序计数器(如当一个方法未执行完,又有另一个线程插入执行另一个方法,当新方法执行完时,可以通过程序计数器标识的位置继续执行之前的方法)。
执行Java方法时,计数器中保存的是字节码文件中的行号,执行native方法是,计数器为空。
- 6.6Java虚拟机启动参数配置
-Xms设置堆的最小空间大小。-Xmx设置堆的最大空间大小。
-Xmn:设置年轻代大小
-XX:NewSize设置新生代最小空间大小。
-XX:MaxNewSize设置新生代最大空间大小。
-XX:PermSize设置永久代最小空间大小。
-XX:MaxPermSize设置永久代最大空间大小。
-Xss设置每个线程的堆栈大小
-XX:+UseParallelGC:选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。
-XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。
以上是 面试题合集(持续更新中。。。) 的全部内容, 来源链接: utcz.com/z/511798.html