java后端开发ms题记录

1.自我介绍
2.基本数据类型有哪些
int 整型 32位 最常用的数据类型
short 短整型 16 常用于节省内存
long 长整型 64位 用于较大整数的计算
flort 浮点型 32位 用于科学计算和高精度计算
double 双精度浮点型 64位
char 字符 可以表示数字、字母、符号
byte 字节 用于文件和网络的字节级别传输
boolen 布尔型 只有true和false两种取值 常用于判断
3. 定义的时候为什么用integer 不用int
integer定义的初始值为null,int定义的初始值是0;为了防止不必要的麻烦(比如成绩 0)
integer初始值为null,int初始值为0
4. string传递的是值还是引用
值传递,string是不可改变的,发生改变则是重新定义的字符串
4.1stringBuffer和stringBuilder
是可改变的,但是stringBuilder线程不安全,但是性能好;被创建在堆上
5.常用的集合框架说一下,哪些是安全的
list、set、hashmap 线程都不安全
list 有arrayList和linkedlist 数组和链表 数组查看快
线程安全的:Hashtable,ConcurrentHashMap,Vector ,CopyOnWriteArrayList ,CopyOnWriteArraySet
线程不安全的:HashMap,ArrayList,LinkedList,HashSet,TreeSet,TreeMap
6. mybatis #和$区别,什么时候用$
#传的值会默认加上双引号作为字符串,$会直接拼在sql中;当作为sql中一部分而非参数时
7.Linux的基本指令说一下
目录:
mkdir创建、rm删除文件或目录、rmdir删除空目录、find查找、mv移动或修改名称、cp 复制文件或目录、pwd显示当前目录
文件:
touch创建、rm删除、head查看前面行tail加行数查看后面对应行数、?查看全部、vi进入编辑修改文件,i开始编辑esc停止编辑:wq保存并关闭:!wq强制保存关闭
压缩
bzip2、zip
解压缩
unzip、tar
安装yum
打开目录 cd加目录名称
查看目录下文件 ls
停止正在运行的程序ctrl+c
关机 shutdown
重启reboot
8. Jvm设置的常用参数?-Xss是什么?
9. Redis的操作,Mysql的操作
10. Springmvc 和springboot一般是单例还是多例 为什么
11. List用for遍历存在的问题,应该用什么

12. sql查询慢怎么看,主要看哪几个参数
执行时间: 观察查询执行所需的时间。如果一个查询花费了相对较长的时间才能返回结果,可能就是慢查询的一个指标。通常,这个时间取决于具体的环境和预期性能。

资源消耗: 查询是否消耗了大量的系统资源,比如 CPU、内存或者磁盘 I/O。这可能会影响系统的整体性能,尤其在高负载时。

慢日志: 数据库通常会记录慢查询日志,这些日志会记录执行时间较长的查询。查看数据库的慢查询日志可以找到慢 SQL 查询的信息,包括执行时间、消耗资源等。

查询执行计划: 使用数据库提供的工具或命令,获取查询的执行计划。执行计划可以显示查询是如何被执行的,以及可能存在的性能瓶颈。

索引优化: 确保数据库表上有适当的索引,有时缺少正确的索引会导致查询变得缓慢。优化索引可以提升查询性能。
普通索引index、唯一索引unique index、全文索引fulltext index、index
增加方式:创建时增加、创建表后增加create index index_name on table_name(column)、修改表增加alter table table_name add index index_name()
索引失效:
运算符不匹配。如果查询中使用的运算符与索引定义的不同,索引会失效。例如,使用LIKE查询字符串而索引的数据类型为数字或日期类型。12345678
函数使用。如果在查询中使用了函数,例如LOWER或UPPER函数,该函数可能会使索引不再有效。原因在于函数会改变查询条件的形式,不再是索引上的原始值。123456
类型转换。如果查询中使用了某种类型的转换,索引会失效。例如,在查询中将字符串转换为数字。12348
表达式复杂。如果查询条件中有复杂的表达式,可能无法使用索引。1
NULL值。如果索引中包含NULL值,NULL值的行将不包括在索引中。因此,在查询时使用索引的列时,如果查询条件使用了NULL,索引将不再有效。12468
OR语句使用。当使用OR语句时,索引可能会失效。例如,“WHERE column1 = 1 OR column2 = 2”,如果这两个列都有索引,但由于OR运算符需要扫描两个索引,因此无法使用它们。
联合索引使用不当。如果查询条件没有使用到创建的索引字段,数据库可能不会使用该索引。568
表连接中的索引失效。如果在表连接查询中,连接条件中的字段没有索引,可能导致索引失效。
索引何时用:
1.原则上来说:一个表需要跟别人做连接的字段都要加索引,比如表A 的A1,A2,A3需要跟其他表发生连接,那么3个字段都要加索引
2.经常用来查询的字段,模糊查询的字段不用, 其他精确查询且字段重复率低的最好需要.比如 varchar字段
3.如果一个表经常用这个字段进行条件查询,这个字段是不是要加索引,要看这个字段的值是什么场景的,如果是枚举的,值是固定的几个,就没多大意义,如果是各式各样的,比如 varchar(100)里面的值重复很少,而且查询不是以like()进行 那么可以考虑加一加.
4.Mysql中Like查询 keyword%,走索引 %keyword%不走索引
5.比如用户名,创建时间,状态,很多常用的条件,就可以尝试建组合索引,注意Where顺序要一样,组合索引,要有组合字段被检索的场景才有用
6.数据重复多的话用位图索引
7.索引多了的表,不建议物理删除数据,最好逻辑删除,索引多了维护起来累,还有,建议索引不要跟数据在一个表空间(Oracle)
8.只要用索引就会拖慢插入 更新的速度,所以自己权衡好
9.每个表不超过三个索引,并不是建的越多性能越好,乱建索引会导致查询慢,具体请看执行计划
10.Oracle高版本按照CBO来优化的,如果CBO觉得不走索引快,那么你建再多的索引都没有用.
监控工具: 使用监控工具来跟踪数据库的性能指标,如查询次数、响应时间等。这些工具可以帮助及时发现慢查询并定位性能问题。下图为使用pigoss监控MySQL和Oracle的慢查询。
13.缓存雪崩
定义:当缓存系统中的大量缓存同时失效或不可用时,请求会直接落到后端系统上,导致后端系统负载骤增,甚至宕机
原因:雪崩效应通常发生在缓存失效的瞬间,这可能是由于缓存过期、缓存服务器故障、缓存击穿等原因导致
影响:
性能下降:后端系统无法及时处理大量请求,导致响应时间增加,系统性能下降。
响应中断:由于后端系统无法承受压力,部分请求可能会超时或直接失败,导致服务中断
措施:
多级缓存(舱壁模式):使用多级缓存架构,如本地缓存、分布式缓存等,减少单一缓存失效对整个系统的影响。
缓存预热:在系统启动或缓存失效前,提前加载热门数据到缓存中,避免大量请求落到后端系统。
缓存失效策略:合理设置缓存的过期时间,并采用合适的缓存失效策略,如LRU(最近最少使用)等。
限流和熔断:通过限制请求的并发量或采用熔断机制来控制请求对后端系统的冲击,保护系统稳定性。
容灾和高可用:配置系统的冗余和故障转移,确保即使其中一部分缓存或后端系统不可用,仍能保持系统的正常运行。

redis支持的五种类型:string、list、set、zset、bmap
14.docker容器
可以将程序及依赖包打包放到docker中,这样就可以在任何安装了docker引擎的服务器上部署包括windows、linux等

15、mybatis中有哪些标签
sql定义 insert、delete、update、select
sql拼接 foreach、if、case、when
foreach中的属性 collection(集合对象)、item(集合元素遍历时别名)、open(常为"(")、close(常为")")、separator(分隔符常为",")

16、springboot如何实现事务
在实现方法上面加上@Transactional增删改查将具有原子性()
什么时候触发事务回滚:默认抛出运行时异常(即继承自RuntimeException的异常)也可以加rollbackfor=Exception.class、error、手动回滚
什么时候不回滚:异常只捕获不跑出、方法中调用了别的对表操作的方法没有加标签

17、秒杀问题
利用redis的单线程特性预减库存处理秒杀超卖问题!!!

在系统初始化时,将商品以及对应的库存数量预先加载到Redis缓存中;(缓存预热)
接收到秒杀请求时,在Redis中进行预减库存(decrement),当Redis中的库存不足时,直接返回秒杀失败,否则继续进行第3步;
将请求放入异步队列中,返回正在排队中;
服务端异步队列(MQ)将请求出队,出队成功的请求可以生成秒杀订单,减少数据库库存,返回秒杀订单详情。

18、面向切面编程 AOP
已经有原始的方法,想增加额外功能不想动原来代码,抽象出来一个通知类,定义出该类要增加的目标方法(这个点叫切入点),
额外功能类和切入点绑定(这个环节叫植入),额外功能与原功能解耦,快速扩展额外功能

19、异步调用多线程
异步请求、并发执行、快速结束
线程池处理

创建线程的几种方式:继承Thread类、实现Runnable接口、实现Callable接口

20、事务的隔离级别
Read Uncommitted (读未提交)。最低的隔离级别,允许脏读,即一个事务可以读取另一个未提交事务的数据。1234567
Read Committed (读提交)。一个事务只能读取已经提交的数据,这样可以避免脏读,但可能出现不可重复读,即在同一事务中多次读取同一行数据时,可能得到不同的结果。
Repeatable Read (可重复读取)。保证在同一事务中多次读取同一行数据时,结果始终一致,但可能出现幻读,即在多次查询时,结果集的行数可能不一致。
Serializable (串行化)。最高的隔离级别,事务按顺序一个接一个执行,避免脏读、不可重复读和幻读,但效率较低。
21、锁


22、重写和重载的区别
重载:

定义位置:重载方法必须在同一个类中定义。
方法名和参数列表:重载方法的方法名相同但参数列表不同,参数类型可以不同,也可以是参数顺序不同。
返回类型:重载方法的返回类型可以不同。
目的:重载的目的是为了提高代码的可读性和简洁性,同时也可以减少编写相似代码的工作量。
重写:

定义位置:重写方法必须在子类中定义。
方法名和参数列表:重写方法的方法名和参数列表必须与父类相同。
返回类型:重写方法的返回类型必须相同或是其子类。
目的:重写的目的是为了改变父类方法的实现,以便适应子类的特定需求。

23、hashmap和hashtable区别
线程安全性:

HashMap 是非线程安全的,这意味着在多线程环境下使用 HashMap 时,需要额外的同步措施来避免数据竞争和不一致的问题。
Hashtable 是线程安全的,它的所有方法都经过了 synchronized 关键字修饰,因此在多线程环境中使用 Hashtable 时,可以避免同步问题。
效率:

由于线程安全性的差异,HashMap 的效率通常比 Hashtable 高,因为 Hashtable 提供了更复杂的同步机制。
Null 值支持:

HashMap 允许键和值为 null,但一个键只能有一个 null 值,多个 null 值会导致运行时错误。
Hashtable 不允许键和值为 null,尝试插入 null 值会导致 NullPointerException。
继承关系:

Hashtable 继承自 Dictionary 类,而 HashMap 继承自 AbstractMap 类。
Hashtable 底层实现基于哈希表加链表,而 HashMap 底层实现基于哈希表。
使用建议:

如果需要线程安全,可以使用 ConcurrentHashMap,它提供了更好的性能和并发性。
如果不需要线程安全,并且对效率有更高要求,可以选择使用 HashMap。

24、AOP和ioc的区别

25、注入方式的区别(@Autowird、@Resource)

26、kafka的注解、如何防止消息丢失

27、创建对象的方式六种
使用new关键字。这是最常见和最基本的方式,通过直接调用类的构造方法来实例化对象。1234567
使用Class类的newInstance方法。这是反射的一个应用,可以通过类的全限定名获取Class对象,然后使用其newInstance方法创建对象。但这种方式在Java 9中已不推荐使用,因为它只能调用公共的无参构造函数。
使用Constructor类的newInstance方法。这也是反射的应用,可以调用任何可见的构造函数,包括带参数的构造函数。134567
使用clone方法。如果原对象实现了Cloneable接口并重写了clone()方法,可以调用该对象的clone()方法来创建对象的副本。1347
使用序列化和反序列化。通过实现Serializable接口,可以将对象转换为字节流(序列化),之后可以从字节流中重新创建对象(反序列化),这个过程可以用于网络传输或持久化对象。
使用第三方库,如Objenesis。利用字节码技术动态生成Constructor类对象,从而创建对象。
28、springmvc的工作流程
用户发送请求至前端控制器(DispatcherServlet)。
DispatcherServlet接收请求并处理。
DispatcherServlet查询处理器映射器(HandlerMapping)找到处理请求的Controller。
DispatcherServlet将请求委托给Controller。
Controller接收请求并处理,处理完成后返回ModelAndView对象。
DispatcherServlet查询视图解析器(ViewResolver)根据ModelAndView信息找到View。
DispatcherServlet将执行结果渲染到View上。
返回响应给用户。
29、bean的生命周期

30、mybatis的工作原理和操作步骤
MyBatis 是一个优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索。
工作原理:
配置 MyBatis 配置文件 (mybatis-config.xml),定义了 MyBatis 的环境配置、事务管理和数据库连接信息。
创建映射文件 (Mapper.xml),包含了 SQL 语句和映射规则。
通过 MyBatis 提供的 SqlSessionFactory 创建 SqlSession。
通过 SqlSession 获取映射器 (Mapper) 接口的实例。
调用映射器接口的方法执行 SQL 操作。
处理结果并返回。
事务提交,关闭 SqlSession。
操作步骤:
添加 MyBatis 依赖到项目中。
配置 mybatis-config.xml 文件。
创建 Mapper 接口。
创建 Mapper.xml 映射文件,编写 SQL 映射。
通过 SqlSessionFactory 获取 SqlSession。
通过 SqlSession 获取 Mapper 接口实例并调用方法。
提交事务,关闭 SqlSession。

mybatis分页
分页可分为逻辑分页和物理分页
逻辑分页是一次性把全部数据查询加载进内存 ,然后再进行分页。这样优点是减少IO次数,适合频繁访问、数据量少的情况。缺点是不适合大数据量,容易造成内存溢出。
物理分页是利用limit语法在数据库中进行分页。他的优点是适合分页大数据量数据。缺点是频繁查询数据库,消耗性能。
mybatis实现分页有三种方式
直接使用SQL语句,利用limit关键字分页(物理分页)
RowBounds(逻辑分页)
第三方插件PageHelper(物理分页)

31、线程池七大参数
1、 corePoolSize 线程池核心线程大小
corePoolSize 是线程池中的一个最小的线程数量,即使这些线程处理空闲状态,他们也不会被销毁,除非设置了allowCoreThreadTimeOut。
2、maximumPoolSize 线程池最大线程数量
线程池能够容纳同时执行的最大线程数,此值大于等于1。一个任务被提交到线程池以后,首先会找有没有空闲并且存活线程,如果有则直接将任务交给这个空闲线程来执行,如果没有则会放到工作队列中,直到工作队列满了,才会创建一个新线程,然后从工作队列的头部取出一个任务交由新线程来处理,而将刚提交的任务放入工作队列尾部。线程池不会无限制的去创建新线程,它会有一个最大线程数量的限制,这个数量即由maximunPoolSize指定。工作队列满,且线程数等于最大线程数,此时再提交任务则会调用拒绝策略。
3、keepAliveTime 多余的空闲线程存活时间
当线程空闲时间达到keepAliveTime值时,多余的线程会被销毁直到只剩下corePoolSize个线程为止。默认情况下:只有当线程池中的线程数大于corePoolSize时keepAliveTime才会起作用,直到线程中的线程数不大于corepoolSIze,
4、unit 空闲线程存活时间单位
keepAliveTime的计量单位
5、workQueue 工作队列
任务被提交给线程池时,会先进入工作队列,任务调度时再从工作队列中取出。
常用工作队列有以下几种:
①ArrayBlockingQueue(数组的有界阻塞队列)
ArrayBlockingQueue 在创建时必须设置大小,按FIFO排序(先进先出)。新任务进来后,会放到该队列的队尾,有界的数组可以防止资源耗尽问题。当线程池中线程数量达到corePoolSize后,再有新任务进来,则会将任务放入该队列的队尾,等待被调度。如果队列已经是满的,则创建一个新线程,如果线程数量已经达到maxPoolSize,则会执行拒绝策略。
②LinkedBlockingQueue(链表的无界阻塞队列)
按 FIFO 排序任务,可以设置容量(有界队列),不设置容量则默认使用 Integer.Max_VALUE 作为容量 (无界队列)。该队列的吞吐量高于 ArrayBlockingQueue。由于该队列的近似无界性,当线程池中线程数量达到corePoolSize后,再有新任务进来,会一直存入该队列,而不会去创建新线程直到maxPoolSize,因此使用该工作队列时,参数maxPoolSize其实是不起作用的。有两个快捷创建线程池的工厂方法 Executors.newSingleThreadExecutor、Executors.newFixedThreadPool,使用了这个队列,并且都没有设置容量(无界队列)。
③SynchronousQueue(一个不缓存任务的阻塞队列)
生产者放入一个任务必须等到消费者取出这个任务。也就是说新任务进来时,不会缓存,而是直接被调度执行该任务,如果没有可用线程,则创建新线程,如果线程数量达到maxPoolSize,则执行拒绝策略。
其 吞 吐 量 通 常 高 于LinkedBlockingQueue。 快捷工厂方法 Executors.newCachedThreadPool 所创建的线程池使用此队列。与前面的队列相比,这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。
④PriorityBlockingQueue(具有优先级的无界阻塞队列)
优先级通过参数Comparator实现。
⑤DelayQueue(这是一个无界阻塞延迟队列)
底层基于 PriorityBlockingQueue 实现的,队列中每个元素都有过期时间,当从队列获取元素(元素出队)时,只有已经过期的元素才会出队,而队列头部的元素是过期最快的元素。快捷工厂方法 Executors.newScheduledThreadPool 所创建的线程池使用此队列。
Java 中的阻塞队列(BlockingQueue)与普通队列相比,有一个重要的特点:在阻塞队列为空时,会阻塞当前线程的元素获取操作。具体来说,在一个线程从一个空的阻塞队列中取元素时,线程会被阻塞,直到阻塞队列中有了元素;当队列中有元素后,被阻塞的线程会自动被唤醒(唤醒过程不需要用户程序干预)。
6、threadFactory 线程工厂
创建一个线程工厂用来创建线程,可以用来设定线程名、是否为daemon线程等等
7、handler 拒绝策略
AbortPolicy:丢弃任务并抛出 RejectedExecutionException 异常。(默认这种)
DiscardPolicy:丢弃任务,但是不抛出异常
DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程) 。也就是当任务被拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务从队尾添加进去,等待执行。
CallerRunsPolicy:谁调用,谁处理。由调用线程(即提交任务给线程池的线程)处理该任务,如果线程池已经被shutdown则直接丢弃
32、数据库varchar和char的区别
长度固定性。char类型是定长字符类型,其长度是固定的;varchar类型是变长字符类型,其长度是可变的。这意味着,当存储字符串时,char类型会在右侧补充空格以达到指定的长度,而varchar类型则仅存储实际长度的数据。
存储效率。char类型在修改数据时效率较高,因为它每次修改的数据长度相同;varchar类型在修改数据时效率较低,因为它每次修改的数据长度可能不同。12
存储空间需求。char类型存储时会占用较多的空间,因为它需要存储初始预计的字符串长度加上实际字符串长度,并且对于定长字段,即使实际数据长度小于定义长度,也会补充空格;varchar类型存储时会占用较少的空间,它只需要存储实际字符串长度加上实际字符串内容。125
适用场景。对于经常修改且长度变化较大的数据,使用varchar类型可能更合适;对于很少变更且长度固定或较短的数据,使用char类型可能更有效。

33、springboot启动类哪些标签、如何启动
Spring Boot启动类通常使用@SpringBootApplication注解,这是一个组合注解,包含@SpringBootConfiguration(表示这是一个Spring Boot配置类)、@EnableAutoConfiguration(启用Spring Boot的自动配置机制)以及@ComponentScan(指定Spring扫描的包路径)。
springboot启动流程
Spring Boot应用的启动流程是一个多阶段的过程,可以从以下几个方面进行概述:
初始化配置。启动过程从`main`方法开始,首先创建一个`SpringApplication`对象。在这个过程中,通过类加载器读取`classpath`下所有的`spring.factories`配置文件,创建初始化配置对象。同时,通知监听器应用程序启动开始,并创建环境对象`Environment`,用于读取环境配置,如`application.yml`。12
创建应用程序上下文。接下来创建`ApplicationContext`(应用上下文),这是Spring容器的主要接口,负责管理应用中的bean。
刷新上下文(启动核心)。这是启动过程中的关键步骤,包括配置工厂对象、注册并实例化bean工厂发布处理器和bean处理器、扫描和解析类、创建bean定义、缓存bean类信息、创建内嵌Web服务器(如Tomcat)、实例化所有bean、创建动态代理对象等。在此过程中,还会发布通知,表明上下文已刷新完成。1
通知监听者。启动程序完成时,通知所有注册的监听者。13
运行应用程序。在所有准备就绪后,Spring Boot应用开始运行。如果是Web应用,此时会启动内嵌的Web服务器。24
打印Banner和版本信息。在启动过程中,还会打印Spring Boot的启动Banner和版本信息。3
记录启动时间。使用`StopWatch`实例记录Spring Boot的启动时间,以便于分析和调试。
总结来说,Spring Boot的启动流程涉及初始化配置、创建应用程序上下文、刷新上下文、通知监听者、运行应用程序等多个阶段,每个阶段都有其特定的任务和目的。

34、循环依赖怎么解决
singletonObjects:这是一级缓存,用于保存已经完全初始化的单例Bean的实例。当Bean创建完成后,它将被放入此缓存中,并且可以通过Bean名称进行访问。
earlySingletonObjects:这是二级缓存,用于保存已经实例化但尚未完全初始化的单例Bean的实例。当Spring框架检测到循环依赖时,会首先将已实例化但未初始化的Bean放入该缓存中,以便后续的依赖注入。一旦所有的依赖都已注入完成,Bean将从此缓存中移除,并放入一级缓存中。
singletonFactories:这是三级缓存,用于保存Bean的工厂类实例。当Spring框架检测到循环依赖时,会先创建一个Bean的工厂类实例并放入该缓存中。这样,当另一个Bean需要引用该Bean时,可以通过工厂类来获取实例,并在后续的实例化过程中完成循环依赖。
35、
kafka如何防止数据丢失消息丢失
Kafka 消息丢失的原因可能有以下几种:

生产者发送的消息未成功写入Kafka。

Kafka broker在消息存储过程中宕机或出错。

Kafka broker处理消息时出错,例如消息格式错误。

消费者未正确消费消息,导致消息丢失。

为了防止数据丢失,Kafka提供了以下机制:

生产者确认:可以设置acks参数,当设置为all或-1时,只有当Leader和所有的Follower都同步消息成功后,才认为消息发送成功。

复制机制:Kafka通过副本机制保证数据的冗余存储,一旦Leader失效,会自动从Follower中选举新的Leader。

消费者确认:通过offset commit可以确保即使在消费者崩溃的情况下,也可以知道消息已被消费。

持久化配置:确保broker配置中的log.dirs指向的目录可靠,且磁盘有足够的空间和健康状态。

posted @ 2024-05-28 15:25  锦瑟流年3344  阅读(2)  评论(0编辑  收藏  举报