面试题合集(持续更新中。。。)

编程

1.Redis缓存的删除策略

  1. 算法

FIFO	First in First out 先近先出。删除进入redis最早的key。

LRU Least Recently Used 最近最早被使用。删除最近一段时间内,被使用过的使用时间离现在最远的key。

LFU Least Frequently Used 最近最不经常使用。删除最近一段时间内,使用频率最少的key。

  1. 具体策略,当有新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缓存

  1. mybatis的一级缓存

一级缓存是SQLSession级别的缓存。

当执行过一次查询操作之后,会在SQLSession中设置缓存,当执行下一次查询,且查询sql及所有参数完全一致时,会直接从一级缓存中获取数据,而不是再次去执行数据库查询。当数据库有commit操作时(Insert,update,delete操作)会完全清除一级缓存。

二级缓存是Mapper级别的缓存。

二级缓存有总开关和分开关。总开关在mybatis配置中设置。分开关在mapper.xml文件中配置。默认是不开启的。

二级缓存开启时,数据查询时会从二级缓存中先取,未取到回去一级缓存中取,最后去数据库中取。

3.springboot启动流程

  1. 创建SpringApplication实例

- 1.1 判断是否为web环境

- 1.2 设置初始化器:从META-INF/spring.factory处读取key为org.springframework.context.ApplicationContextInitializer的value,并进行实例化

- 1.3 设置监听器

- 1.4 推断应用入口

  1. 执行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中是否存在内存泄露?举例?

  1. Java中是存在内存泄露的

  1. 示例

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

回到顶部