Java面试题(持续更新中...)

news/2024/10/15 16:14:11

事务的四大特性

原子性,隔离性,持久性,一致性

事务的隔离级别和现象

  1. 读未提交:可能产生脏读,读取到未提交的数据
  2. 读已提交:可能产生不可重复读取问题,A事务中读取到B事务已提交的数据,导致两次读取数据不一致
  3. 可重复读:可能产生幻读问题,A事务中查询到B事务插入的数据,导致两次查询条数不一致
  4. 可序列化:最高级别,强制事务序列化执行,独占锁,并发效率慢

不可重复读和幻读的区别

不可重复读的重点在修改,两次查询数据不同

幻读的重点在新增和删除,两次查询行数不同

Spring如何解决的循环依赖问题

首先说下什么是循环依赖:A对象依赖于B对象,B对象依赖于A对象。

Spring解决循环依赖的核心思想在于提前曝光,首先创建实例化A,并在三级缓存中保存实例化A的lambda表达式以便获取A实例,然后去实例化B,在实例化B的时候就可以取到A了,后面再去实例化A。

当我没有循环依赖和AOP时,这个三级缓存是没有在后续用到的。

线程有几个状态

6个状态分别是:新建,运行,阻塞,等待,超时等待,终止

wait和sleep的区别

  1. wait来自Object类,Sleep来自Thread类。
  2. wait会释放锁,sleep不会。
  3. wait必须在同步代码块中执行,sleep可以随便执行。
  4. wait可以捕获异常,sleep必须捕获异常。

synchronized和lock锁的区别

sync可重入锁,不可中断,非公平锁

lock可重入锁,可以判断锁,非公平锁(可设置)

什么是可重入锁

只要持有该锁,再次进入代码块就不需要争抢锁,如递归,可以一直进进出出,不会出现死锁

工作中遇到过的异常、

运行时异常,IO异常,数据库连接异常,ClassNotfound异常,OutOfMemoryError异常,ConcurrentModification并发修改异常

信号量和互斥锁的区别

信号量:一次可以被多个线程持有,资源调度

互斥锁:一次只能被一个线程持有,资源互斥

什么是AQS

抽象对象同步器,基于CLH队列(双向链表),用volatile修饰共享状态(state),线程通过CAS去改变状态符,成功则获取锁成功,失败则进入等待队列,等待被唤醒。

Executors线程池工厂的三大方法

newSingleThreadExecutor()单个线程池,newFixedThreadPool(n)创建固定大小的线程池,newCachedThreadPool()可伸缩的线程池

单例模式

饿汉式:直接创建对象。

懒汉式:使用时创建对象,双重检测锁和volatile关键字解决并发问题。

CAS(比较并交换—乐观锁)机制

比较当前工作内存中的值和主内存中的值,如果这个值是期望的,则执行操作。否则不执行。

  • 存在ABA狸猫换太子问题
    • 使用增加版本号可以解决,乐观锁机制
    • JUC提供了原子时间戳引用类AtomicStampedReference,可以解决ABA问题

怎么排查死锁问题

定位进程:jps -l

堆栈跟踪:jstack 进程号

JVM内存模型

  1. 堆:内存对象
  2. 栈:局部变量,方法出口,操作数,动态链接
  3. 方法区(元空间):常量,静态变量,类信息
  4. 本地方法栈:native方法
  5. 程序计数器:反编译代码的执行顺序号

JVM参数介绍

-Xmx最大堆内存

-Xms初始堆内存

JVM垃圾回收机制

JVM:年轻代内存满了之后会发生MINORGC,使用可达性分析算法,将引用的对象放入e0区,为引用的对象就进行minorgc垃圾回收,每发生一次minorgc,存活对象会在s0和s1区进行切换,当s区满了和分代年龄15,会进入老年代,老年代满了会发生fullgc,如果fullgc也释放不了对象,而新对象一直在产生并放入老年代就会内存溢出OOM。

JVM调优:判断该服务业务代码会执行多少秒*每秒产生多少M的对象,并设置年轻代Eden(8:1:1)的大小(业务代码刚好执行完成,发生minorgc进行回收),剩下的内存就分配给老年代。

G1收集器(C++语言实现),可以通过参数设置最大停顿时间,到达这个停顿时间就会发生gc,需要考虑业务场景,避免对象过大或者年龄太大,多数对象进入老年代。

JVM垃圾回收算法

  • 引用计数法:程序计数器
  • 年轻代-幸存者区:复制算法
  • 老年代:
    • 标记清除(标记存活的对象,没有标记的对象进行清除,会产生内存碎片)
    • 标记整理(标记存活的对象,将存活的对象移动到一端,没有标记的对象进行清除,不会产生内存碎片)

为什么要设计STW(回收时停顿)

如果没有,fullgc和minorgc时会误删除程序中的非垃圾对象。

s区的大对象(大于50%)会直接放去老年代。

minorgc和fullgc会产生STW。

为什么堆里面要划分年轻代和老年代?

答:如果不划分的话,垃圾对象一直堆积不回收,等真正发生gc的时候,时间会超级长。

年轻代为什么要有s0和s1区

  1. 如果没有的话会导致发生minorgc就把存活对象放入老年代了导致fullgc,停顿时间长
  2. 如果只有一个s区,复制算法会产生内存碎片,eden区和s0区会互相复制,比如说eden和s0区各有存活的对象,eden将存活对象放入s0区,会导致内存不连续
  3. 为什么要有两个区,经过权衡后的最优解

JMM内存模型

主要分为主内存(堆)和工作内存(栈),工作内存是主内存和一份拷贝,主要操作有:锁定lock,解锁unlock,读取read,载入load,使用use,赋值assign,存储store,写入write

TCP三次握手

二次握手的问题:客户端的第一次请求时延误发送到了服务端,服务端成功接收到了请求(但在客户端认为这个请求已经失败了),第二次响应时服务端向客户端响应,客户端认为该请求已失败,并不会接收这次响应,服务端会一直死死的等待(死锁)客户端发送数据报文,造成资源消耗(如果客户端重新建立连接,会建立一个新的通道,上一个通道会一直存在)。如果是三次握手的情况下,第三次握手如果服务端在一段时间内没接收到客户端的响应,就会关闭这个连接通道。

第一次握手,客户端向服务端发送请求建立连接。

第二次握手,服务端向客户端响应是否确认建立连接。

第三次握手,客户端会向服务端发送一个确认建立连接。

三次握手的目的:防止已失效的连接请求报文突然传送到了服务端

TCP四次挥手

由于TCP双向通道互相独立所导致的,

  1. c向s发送"我要关闭连接"。
  2. s向c发送"我知道了",并且s进入半关闭状态(可以接收数据,不可以发送数据)。
  3. s向c发送"我要断开连接了,你确认下",进入最后确认状态。
  4. c向s发送"可以断开",s接收到后会进行关闭连接,c等待2msl(数据报文一来一回的最大时间),进入关闭状态。

ArraysList扩容机制

默认初始容量10,扩容原始容量的1.5倍取整,扩容因子1

Vector向量扩容机制

线程安全sync锁

默认初始容量10,扩容原始容量的2倍取整,扩容因子1

HashMap扩容机制

默认初始容量16,扩容倍数2,扩容因子0.75

数组长度大于64并且链表长度大于等于8(每产生哈希冲突,进行equal比较,hash码相同替换,不同插入链表)->链表转变为红黑树,链表长度小于等于6则从红黑数转为链表,jdk1.7采用头插,jdk1.8采用尾插。

HashMap数据结构

HashMap的实现是基于数组和链表(或红黑树)的组合实现的。数组被初始化为一定数量的桶,每个桶可以包含一个链表或者红黑树。当使用put()方法向HashMap中添加一个键值对时,首先会对键进行哈希计算,然后找到对应的桶。如果桶为空,就将键值对插入到桶中。如果桶不为空,就遍历桶中的所有键值对,查找是否已经存在相同的键,如果存在则更新值,否则将新的键值对插入到桶中。

ConcurrentHashMap数据结构

1.7 采用ReentrantLock+Segment+HashEntry分段锁的思想,对每个Segment桶位加锁。

1.8 舍弃了分段锁的思想,更加接近hashmap,采用synchronized+CAS+HashEntry+红黑树,对每个数组元素加锁

HashMap寻址

put方法实际有4个参数,第一个参数hash值是32位,左移16位并"高16位和低16位进行异或得到的值"让本就随机的值更加随机,尽量避免hash碰撞,提高查询效率。

HashMap为什么线程不安全

因为put方法执行的时候,首先要获取插入的位置索引,如果此时有另一个线程进入获取了同样的索引并插入,当前线程如果再插入会覆盖插入的数据,导致数据不一致

并发的三大特性

原子性,可见性,有序性

双亲委派机制

类加载器:BootStrapClassLoader主加载器,ExtClassLoader扩展加载器,AppClassLoader系统类加载器以及线程上下文加载器,可以自定义加载器。

双亲委派:向上委派到顶层加载器,向下查找加载路径

守护线程

守护线程最后关闭,守护线程不可以用线程池创建,线程池创建的守护线程都会转换成用户线程,守护线程中创建线程,创建的还是守护线程

线程池执行流程

超过核心线程(甲方),就放入任务队列(排期),任务排不完,放入最大线程(外包),最大线程超过空闲时间,执行拒绝策略(辞退)

keep超时时间,最大线程中有线程空闲了,超过这个时间就回收线程

线程池七大参数

  1. corePoolSize 线程池核心线程大小
  2. maximumPoolSize 线程池最大线程数量
  3. keepAliveTime 空闲线程存活时间
  4. unit 空闲线程存活时间单位
  5. workQueue 工作队列
  6. threadFactory 线程工厂
  7. handler 拒绝策略
    1. AbortPolicy:丢弃任务并抛出异常
    2. DiscardPolicy:静默丢弃任务,不抛异常
    3. DiscardOldestPolicy:丢弃最前面的任务,新任务加入队列
    4. CallerRunsPolicy:由调用线程执行该任务,不会丢弃

spring是什么

  • 是一个轻量级的简化开发的框架,管理Bean的容器,各个框架的中间人(整合各种框架)
  • ioc容器用于管理bean,使用aop解决oop代码重复的问题
  • springmvc是spring对web框架的一个解决方案,总前端控制器servlet视图解析器生成视图到页面。
  • springboot是spring的快速开发包,相当于spring和springmvc的整合,约定大于配置。

spring对象的生命周期

  1. 解析类得到BeanDefinition定义对象。
  2. 推断构造方法。
  3. 进行实例化,得到对象。
  4. 给对象中的@Autowired注解属性赋值。
  5. 回调Aware方法(获取容器,用于访问容器中其他的Bean)。
  6. 调用初始化前的方法。
  7. 调用初始化。
  8. 调用初始化后的方法。
  9. 将单例Bean放入单例池。
  10. 使用Bean。
  11. 销毁Bean。

bean的作用域

singleton单例,prototype多例,request一个请求一个单例,session一个session一个单例,application一个上下文一个单例,webSocket一个连接一个单例

spring的单例Bean是线程安全的吗

不是,框架并没有对多线程进行处理,使用双重检测锁和可见性关键字,ThreadLocal或者加锁。

spring的自动装配原理

@Import导入了扫描META-INFO/spring.factories文件,文件中配置了各个Starter中的配置类,配置类中使用@Bean注入,各个starter需要遵守springboot的约定

explain执行计划

主要优化看type字段,执行效率:避免(All和index) All全表<index遍历索引树<range检索范围数据<ref非唯一性索引扫描<eq_ref唯一性索引扫描<system表中只有一条数据<const通过索引一次命中,匹配一条数据

什么是MVCC机制

多版本并发控制的一种方法,通过版本链(readView维护活动的事务Id,排序成一个数组从小到大,数组外左边的是已提交的事务可以访问,数组外右边的是未提交的不可访问),实现多版本,可并发读写,通过readView,生成策略的不同,实现不同的隔离级别

RDB和AOP的区别

RDB:快照模式,通过配置文件save 600 3设置,600秒内至少有3个key发生修改,产生快照替换原有快照。

AOF:文件追加模式,记录修改动作到文件中,缺省一秒追加一次,appendfsync: 进行配置。

区别:AOF效率低于RDB,AOF采用追加RDB采用快照,RDB(如果死机后丢失未生成快照的数据)没有AOP(会丢失一秒内的数据,并不会影响之前存在的数据)数据安全

redis为什么采用单线程

只在处理网络请求时采用单线程,完成基于内存操作,非阻塞多路IO复用(使用select,可以建立多个socket连接处理IO非多线程),避免了上下文和多线程切换避免加锁产生问题引起资源消耗

什么是缓存雪崩、缓存击穿、缓存穿透?

缓存雪崩:缓存同一时间大面积失效,过期时间尽量间隔随机,缓存预热-启动时将数据同步到缓存。

缓存穿透:大量请求同时访问不存在的数据,都会到mysql查询,一般是受到了攻击,可通过缓存key-null➕过期时间,布隆过滤器,代码校验来解决。

缓存击穿:是指热点数据失效了,大量并发查同一条数据导致崩溃,可以通过热点数据永不过期-修改时同步缓存或者失效后数据库访问时加互斥锁

怎么实现接口幂等性(多次点击导致数据问题)

使用乐观锁机制,增加唯一业务流水号

HTTP和TCP的区别

HTTP位于应用层,http是基于TCP的一个短连接。

TCP协议位于传输层,TCP协议支持长连接和短连接。

redis基本数据类型

5种常见数据类型,string,hash,list,set,zset

mysql慢查询日志分析

可以通过命令或者my.cnf配置开启慢查询日志记录,mysql提供了工具mysqldumpslow可以进行分析

synchronized锁升级

Java虚拟机对synchronized的优化,大多数情况下锁不存在多线程竞争,所以向第一个现场偏护,一旦出现多线程竞争的情况下,就会从偏向锁升级为轻量级锁(自旋锁),如果自旋执行了一定次数的CAS(比较并交换)还没有获取到锁,就会从轻量级锁膨胀为重量级锁,只允许一个线程进入

进程和线程的区别

进程是系统分配资源的最小单位,线程是系统调度的最小单位。

一个程序至少有一个进程,一个进程至少有一个线程。

Java线程调度算法是时间片轮转方式。

pageHelper分页原理

使用拦截器拦截并重写SQL

mybatis #和$的区别

预编译,参数默认会加单引号,使用PreparedStatement的set方法赋值,用于取值场景,预防sql注入。

$ sql拼接,可用于动态表名/字段场景,会导致sql注入。

什么是可达性分析算法

GCRoot(虚拟机栈的引用)开始向下搜索,搜索走过的路径称为引用链,当一个对象的gc root没有任何引用链时,证明这个对象是不可用,不可达的。

什么是行锁,什么是表锁

行锁是排他锁,防止其它事务修改此行

表锁是共享读锁,独占写锁

redis的过期策略以及内存淘汰机制

过期策略

定期加惰性

定期删除-每过100毫秒检查key是否过期,过期就删除

惰性删除-获取key的时候检查是否过期,过期就删除

内存淘汰策略:

如果定期删除没删除key,也没请求key进行惰性删除,此时内存就会越来越大,可以在配置文件里配置内存淘汰策略,如:从已设置过期的key中取出最近没有使用过的key淘汰

redis分布式锁的实现

setnx加过期时间expire,但不是同步执行的,可能导致死锁。

set中有很复杂的参数,可以把setnx和expire组成一条命令使用。

redis延时队列的实现

使用zset,并设置个时间戳,然后查询出所有延时任务,找出需要进行处理的延时任务,通过时间戳判断是否大于当前系统的时间,大于就处理这个消息。

如何实现数据一致性

延时双删实现mysql和redis的数据一致性

  1. 删除redis缓存数据
  2. 更新数据库数据(这里可能有其他事务修改数据并成功放入缓存,导致redis数据不是最新的)
  3. 延时同步时间(等待其他更新缓存操作完成)
  4. 删除redis缓存数据

如何避免消息重复发送和重复消费

重复发送:MQ内部针对每条生产者发送的消息生成一个inner-msg-id,作为去重和幂等的依据

重复消费:在消息消费时,要求消息体中必须要有一个bizId

常见加密算法类型

AES: 对称加密-加解密用同一把钥匙(密钥)

RSA: 非对称加密-加密用公钥(密钥),解密用私钥(密钥)

linux常用指令

tail -f 实时监听日志

tail -n 100 查看末尾100行的日志

netstat -apn | grep 8080 查询指定端口的信息

ps -ef | grep pid 查询指定进程的信息

top 查看cpu使用情况

df -h 查看硬盘使用情况

free -h 查看内存使用情况

Innodb和Myisam存储引擎的区别

Innodb支持事务、必须有主键、支持表/行锁、支持MVCC模式、支持外键

Myisam不支持事务、非必须有外键、只支持表锁、不支持MVCC模式、不支持外键

Mysql主从同步的基本原理

  1. 主库将修改语句保存到binlog日志中
  2. 主库创建一个线程将binlog日志发送到从库
  3. 从库创建一个IO线程读取binlog日志
  4. 从库解析binlog日志中的语句执行

redis的内存淘汰策略

  1. noenviction:不清除数据,只是返回错误,这样会导致浪费掉更多的内存,对大多数写命令(DEL 命令和其他的少数命令例外)
  2. allkeys-lru:从所有的数据集中挑选最近最少使用的数据淘汰,以供新数据使用
  3. volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰,以供新数据使用
  4. allkeys-random:从所有数据集中任意选择数据淘汰,以供新数据使用
  5. volatile-random:从已设置过期时间的数据集中任意选择数据淘汰,以供新数据使用
  6. volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰,以供新数据使用
  7. volatile-lfu:从所有配置了过期时间的键中淘汰使用频率最少的键
  8. allkeys-lfu:从所有键中淘汰使用频率最少的键

说几个事务失效的场景

  1. 非public方法上加事务注解会失效,原因:AOP代理对象过滤了非public方法
  2. 同类中方法互调事务会失效,原因:绕过了AOP代理对象
  3. 数据库引擎不支持事务
  4. 异常被catch吃掉了

redis持久化机制

aof:丢失数据少,恢复速度慢,写操作追加文件(日志记录),占用更多磁盘

rdb:丢失数据多,恢复速度快,间隔一段时间生成快照,文件较小

短url压缩算法

  1. 使用md5加密,分四段,随机取一段
  2. 使用放号器,初始0,新请求递增,转换成64进制(a-zA-Z0-9)
  3. 将短链接服务器和真实路径做个映射保存到redis
    • 或者使用LUR本地缓存,存储最近访问的n个映射,更新最近映射的时间,淘汰最近未访问的映射
  4. 根据映射使用301或302重定向到真实地址
    • 301永久重定向:无法记录点击率
    • 302临时重定向:可以记录点击率

限流、熔断、降级

熔断-如果某个服务宕机,返回给前端友好信息,会定时检查服务是否恢复,慢慢恢复使用

限流-页面限制每秒的请求量QPS

降级-如果某个时间段,请求量太大,服务器压力太大,可以关闭一些不必要的功能,保留一些核心功能

springmvc执行流程

前端控制器DispatcherServlet ->

处理器映射器handlerMapping ->

处理器适配器handlerAdapter ->

ModelAndView ->

视图解析器ViewReslove处理ModelAndView ->

View视图渲染到页面

数据库调优

表结构建立的时候字段长度尽量不要浪费,因为mysql底层对内存页的数据存储是16kb,如果一行数据大小为16kb,那么只能存储一条数据,很恐怖。

内存页是什么

mysql的每次IO只能读取一个内存页的数据。

b+数的每个节点就是一个内存页的数据。

Mysql索引类型

聚簇索引(主键索引)

辅助索引(唯一索引、普通索引、组合索引)

倒排索引(全文索引)

覆盖索引--不需要回表查询

threadlocal可能会导致什么问题

内存泄露问题,因为底层使用的threadlocalmap,key是软引用对象,可能gc的时候把key回收了,而value还在内存中,所以需要显式清除

数据库中的最左匹配原则

针对联合索引

  • 联合索引(a,b,c)相当于建立了索引:(a),(a,b),(a,b,c)
  • mysql内部优化器,会自动排序where条件,并匹配组合索引

数据库中的b+树存储逻辑

b+树根节点不存储数据只存储键,叶子节点存放(聚集索引存放数据,非聚集索引存放主键和索引列),树的各个页之间(page16kb)是通过双向链表连接的,而叶子节点数据是通过单向链表连接的

AOP通知类型

前置通知,后置通知,环绕通知,异常通知,最终通知

幂等是什么

接口只允许调用一次,对数据的影响只会触发一次

接口幂等性(多次点击导致数据问题),接口多次调用和一次调用结果相等

RabbitMQ如何工作?

1. 生产者
- 创建交换机,指定交换机类型
- 创建队列
- 队列绑定交换机并可以指定routingKey路由键
- 发送消息到交换机并可以指定routingKey
1. 消费者
- 创建队列
- 监听队列

RabbitMQ交换机各个模式区别和作用?

2. fanout,广播模式,发送消息到所有绑定的队列
3. direct,路由模式,发送消息到指定routingKey的队列
4. topics,主题模式,发送消息到指定routingKey(绑定时可以使用通配符)的队列
5. headers和direct交换机完全一致,但性能差很多,几乎不用了

RabbitMQ工作流程

  • ConnectionFactory --> Connection --> Channel --> 创建交换机 --> 创建队列 --> 队列绑定交换机 --> 发送消息/接收消息
  • 直接发送到队列:底层使用了默认交换机

RabbitMQ常见故障的解决思路

RabbitMQ服务器宕机消息丢失

消息队列默认是持久化到硬盘上的,不惧怕重启

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/71867.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

数据采集作业1

作业一 (1)实验内容 o 要求:用requests和BeautifulSoup库方法定向爬取给定网址(http://www.shanghairanking.cn/rankings/bcur/2020 )的数据,屏幕打印爬取的大学排名信息。 o 输出信息: 排名 学校名称 省市 学校类型 总分 1 清华大学 北京 综合 852.5 2 ...... 代码如下…

如何制作精美ppt(1)

现阶段人工智能有生成式人工智能、大语言模型、和ChatGPT,这三者之间为层级关系,生成式人工智能包含文本生成、图像生成、音频生成、视频生成。 现阶段推荐可使用的软件有:海螺AI 文小言(百度) Kimi智能助手(写论文适用) 智谱清言 制作过程要当成一种交流 1 沟通:作为上…

luogu 模拟赛

A.带余除法 我们不难考虑找出 \(q\) 的上下界,不难发现范围是 \([\lfloor\frac{n}{k+1}\rfloor+1,\lfloor\frac{n}{k}\rfloor]\)。当然这个区间可能为空。只需算出区间长度即可。 B.奖牌排序 不难考虑到分别按照三个关键字排序,然后对于每个小朋友找到每个关键字下的排名(同…

vue+wangEditor编辑器,上传图片请求后台接口

来吧,先给大家看一下,是否是你想要的简单轻便编辑器的效果。父组件:<EditorView :content="value" @change="grtUrl"/><script> import EditorView from "@/components/EditorView"; export default {components: {EditorView}},…

汽车开发流程管理工具赋能安全与质量

经纬恒润能够提供Stages的咨询及工程服务能力,同时在ALM实施、ASPICE、功能安全、预期功能安全等有着丰富的咨询经验,帮助客户共同构建一个更高的安全标准和质量水平。 随着数字化、人工智能、自动化系统及物联网技术的迅速发展,工程驱动型企业正面临重大转型挑战,亟…

汽车电控 01

汽车电控1、车体 本身必要的电子设备 如 发动机,底盘,车身电子控制系统等。 2、车载 不是必要的电子设备 如 音响 空调 导航。车用传感器温度传感器压力传感器转速传感器爆震传感器流量传感器移位传感器气体浓度传感器

网络数据请求

测试可跳过域名校验

springboot 项目引入tk或者jpa 访问报错

今天弄新框架的时候,遇到个莫名其妙的问题,如下: springboot 项目引入tk 后 Caused by: java.lang.IllegalStateException: Failed to asynchronously initialize native EntityManagerFactory: java.lang.NoSuchMethodError: javax.persistence.ValidationMode javax.persi…