2023高级Java面试题(付部分答案)

数据库篇

MySQL数据库相关:

1.MySQL有哪些常见的存储引擎?

innoDB,myISAM,MEMORY

2.索引的原理是什么?

innoDB和myISAM对应 B+tree, memory对应hash

3.MySQL三种日志分别起到什么作用?(redoLog,undoLog,binLog)

redolog\undolog\binlog

mysql中有缓存池机制 减少io开销

redo log:是InnoDB存储引擎独有的,它让MySQL拥有了崩溃恢复能力

刷盘时机:redolog有三种机制:

0 :设表示每次事务提交时不进行刷盘操作,通过定时任务触发
1 :表示每次事务提交时都将进行刷盘操作(默认值)
2 :表示每次事务提交时都只把 redo log buffer 内容写入 page cache

binlog: 按顺序记录表操作,可以说MySQL数据库的数据备份、主备、主主、主从都离不开binlog,需要依靠binlog来同步数据,保证数据一致性

刷盘时机:write和fsync的时机,可以由参数sync_binlog控制,默认是0。
为0的时候,表示每次提交事务都只write,由系统自行判断什么时候执行fsync。
为1的时候,表示每次提交事务都会执行fsync,就如同 redo log 日志刷盘流程 一样。
为N的时候,表示累计的提交事务达到N时才进行刷盘流程

undo log :保证事务的原子性,所有事务进行的修改都会先记录到这个回滚日志中,然后再执行相关的操作

为什么选择B+树索引?

我的理解简单来说就是:

1.因为B+tree中间节点置存储索引,只有在叶子结点存储了数据以及指向该数据的索引,所以减少了io次数,相当于每次搜索只需读取一次磁盘

2.叶子结点的元素也是有序排列的

什么情况下会出现索引失效?

1.若语句使用复合索引查询,不符合最左原则的查询

2.where条件中使用到了计算、函数、类型转换 ( 自动或手动 ) 。

3.is null 可以使用索引,is not null 无法使用索引。

4.使用or切前后存在非索引的列

5.like以%开头的

6.不同字符集的比较,不同类型的比较

如何查看执行计划?

explain语句:

id:id相同从上倒下执行,id不同越大的越先执行

select_type:查询类型-SIMPLE(简单的单句查询),PRIMARY-(包含复杂子查询的最外层查询),SUBQUERY-(子查询),DERIVED-(在from列表中包含的子查询被标记为derived(衍生)不是很懂)UNION-(union关联的后一个语句)UNION RESULT-(从union表获取最终结果的语句)

type:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

possible_keys:查询涉及到的字段上存在的索引

key:实际使用的索引

。。。。。。。key_len,ref,rows,extra

如何优化SQL查询?

1:避免使用select * 进行查询,需要哪些字段查询哪些字段,insert的时候明确插入的字段;

2:在where条件的字段、order by的字段、表关联的字段,建立合适的索引;

3:通过explain查看执行计划,查看是否走索引,是全表扫描、范围扫描,还是根据索引查找等;

4:如果是组合索引,则进行最左匹配原则。

5:减少模糊查询的使用,如果需要使用like查询,则使用 like ’test%‘,避免使用 like ’%test‘,%在前,会导致索引失效;

6:如果对数据实时性要求不高且含有复杂计算逻辑的查询,可以定时将计算好的数据刷新到临时表,这样可以提高查询效率;

7:建立索引的时候,选择基数比较大的字段,像状态字段之类的,可能只有两三种值,则没必要建立索引,建立索引反而会影响删除和插入的性能;

8:当只需要查询一条数据的时候,加上limit 1;

9:减少not in 的使用,如果需要使用,则使用not exists,因为not in 不会走索引;

10:尽可能的避免or的使用,因为这会放弃索引,从而进行全表查询,可以使用 union all

MySQL主从复制原理?

数据库死锁的原因?如何快速定位并解决?

事务之间对资源访问顺序的交替

并发修改同一个记录

索引不当导致全部扫描

事务封锁范围大且相互等待

事务隔离级别

事务有哪些隔离级别?

由低到高分别为Read uncommitted 、Read committed 、Repeatable read 、Serializable

读未提交 . 读提交. 重复读(就是在开始读取数据(事务开启)时,不再允许修改操作). 序列化.

每种隔离级别会导致什么问题?

脏读:读到未提交的事务

不可重复读:同一个事务两次读取不一致

幻读:同一事务两次读取到的数量不一致

三范式?1.保每列保持原子性,2.确保表中的每列都和主键相关,3.确保每列都和主键列直接相关,而不是间接相关

mysql 和 oracle默认情况下分别采用哪种隔离级别?

mysql默认rr oracle默认rc

mysql如何解决幻读的?

加间隙锁,对数据区间加锁

mvcc多版本并发控制

中间件篇

MQ的相关问题

你用过消息队列吗?用了哪个消息队列?

用过,rabbitmq

在使用MQ的时候怎么确保消息 100% 不丢失?

从两个层面出发,消息生产者,队列持久化,消息消费者

消息生产者开启发送确认,获取交换机接收成功标识

队列持久化

消费者开启手动确认消费机制

other :还可以使用死信队列处理消费失败的数据

怎么解决消息的重复消费问题?

出现的原因,可能同一条消息,生产者重复发送(由于网络延迟等不可控因素)

应从消费者端解决:

消费端处理消息的业务逻辑保持幂等性

可以用redis的set存储消息唯一id

也可以使用数据库的排他锁

如何实现顺序消息?

1.可以仅使用一个消费者自然实现顺序消费

2.版本号的方式实现

3.分组且加版本号

如何解决引入消息后的事务问题?

如果问到就反问一下什么是引入消息后的事务问题,因为一般引入事务业务上一个消息就是一个原子的操作,如果涉及多dml操作或者多个微服务,只要在消费者方法上加事务控制或者引入分布式事务seta

分库分表相关问题

你用过分库分表吗?

用过,mycat,shardingsphare-JDBC

如何实现单个维度的非sharding-key 的查询问题

?比如通过userID 作为 sharding-key,那么如何实现基于userName进行查询?(映射法、基因法)

一般我们是不建议这样设计的,如果一定会出现这种场景且使用较频繁的话,可以建个中间表的方式先通过userName找到userID

如何实现多个维度的多个字段非 sharding-key 如何查询?时间、用户名、类别等...

没做过,一般都是尽全力配合分表规则在业务上规避掉这些情况

多维度查询需要配合其他查询引擎,那么如何实现数据同步?如何保证双写的一致性?

1.根据常见查询场景,增加相应字段的组合索引

2.引入ES,写操作通过同步机制如canal同步到es,查询是es支持多维度查询

很多情况下并不是一开始就实现分库分表,等我们需要分库分表的时候如何进行数据迁移?

1.本次我做的分表分库是通过跑代码的方式分表分库的

Redis

用过Redis吗?Redis支持哪些常见的数据结构?

用过 ,redis实现多种结构底层是使用了redisObject,包含三个重要属性

type(String,List,Hash,Set,Zset),encoding(value的底层编码),ptr

Redis的线程模型

6.0前单线程,6.0后多线程,main线负责分发支线负责返回客户端结果

Redis如何保证数据不丢失的(如何实现持久化)?

RDB 持久化机制,是对 Redis 中的数据执行周期性的持久化

AOF 机制对每条写入命令作为日志

AOF 和 RDB的实现原理?

AOF:日志的方式同步,每一秒会有一个线程同步数据,追加的方式,丢失风险小,文件会偏大

RDB:通过快照的形式5分钟甚至更久时间同步一次数据,性能影响小,丢失风险大

Redis如何实现高可用?

高可用:一是数据尽量不丢失,二是保证服务尽可能可用

1,不丢失:RDB,AOF

  1. 可用:主从模式哨兵模式集群模式

什么是缓存穿透,缓存击穿,缓存雪崩?分别如何预防解决?

穿透:缓存,数据库都没有数据,导致用户误解不断发起请求---缓存空对象,布隆过滤器

击穿:大量缓存同时过期,同时大量访问io操作打入数据库---热点数据,使用互斥锁排队

雪崩:与雪崩类似--互斥锁,缓存预热(提前加载),缓存屏障

分布式锁相关问题

用过分布式锁吗?用什么实现的分布式锁?

没用过,但是知道可以使用

a.基于数据库,b.redis,c.zookeeper,了解过redis实现的分布式锁,主要是setnx命令的排他特性,获取锁的操作关键词:同步,设置超时时间

有没有用过基于redis分布式锁?有没有用过基于Zookeeper的分布式锁?

如何给锁设置合理的加锁时间?锁超时了怎么办?Redisson看门狗的原理?

加锁时间应当超过业务执行时间,若业务未完但锁以过期,可能会释放其他线程的锁,所以可以使用lockwatchdogtime,只要占用锁成功,就会另起一个线程每单位时间延长一次锁过期时间。

Redis如何解决集群情况下分布式锁的可靠性?

自动续航,

RedLock算法的原理?

1.redis集群的场景下,只要半数结点返回获取锁成功则本次获取锁成功,类似选举算法

2.锁记录结构为 哈希表,lockname-(uuid,计数器)

并发编程篇

锁相关

说一下synchronized 底层实现原理?

被该关键词标注的代码块,线程在执行前必须先获取对象锁,而释放锁的动作会由jvm完成

说一下synchronized、volatile、CAS 的区别?

1、synchronized 是悲观锁,属于抢占式,会引起其他线程阻塞。

2、volatile 提供多线程共享变量可见性和禁止指令重排序优化。

3、CAS自旋锁, 是基于冲突检测(版本控制)的乐观锁(非阻塞

synchronized 和 Lock 有什么区别?

1.作用位置:sync加在代码块,方法上,Lock用在方法中

2.解锁方式:sync由jvm自动解锁,Lock需要在finally中手动解锁

3.锁原理:sync使用悲观锁机制,cas使用自旋锁,属于乐观锁机制

什么是CAS,CAS的原理?

CAS:Compare and Swap,即比较再交换CAS 操作包含三个操作数 -- 内存位置、预期数值和新值。CAS 的实现逻辑是将内存位置处的数值与预期数值想比较,若相等,则将内存位置处的值替换为新值。若不相等,则不做任何操作。

CAS有什么缺点?如何解决CAS中常见的ABA问题?

ABA问题:增加了预期值来解决更新前后版本不一致的问题

循环时间长,开销大;

只能对单共享变量的场景

AQS的原理,AQS的实现过程是什么?

AQS:抽闲队列同步器

实现过程:关键参数--volatiel修饰的state和NodeCLH队列,ConditionObject条件变量

有没有用过读写锁ReentrantReadWriteLock,说一下ReentrantReadWriteLock的原理?

读写锁可以说有两个锁(读,写锁)组成,读锁可多次获取,写锁是独占锁

线程池相关

有哪几类线程池?如何创建线程池?

答:1.newCachedThreadPool 可缓存的线程池,任务增加时可以自动添加新线程,线程池的容量不限制。比较适合处理执行时间比较小的任务

2.newFixedThreadPool 固定数目,任务失败时自动补充,可以用于已知并发压力的情况下,对线程数做限制。

3.newScheduledThreadPool 创建一个支持定时及周期性的任务执行的线程池。适用于需要多个后台线程执行周期任务的场景。

4.newSingleThreadExecutor. 创建一个单线程化的Executor,线程异常结束,会创建一个新的线程,能确保任务按指定顺序(FIFO,LIFO,优先级)执行。可以用于需要保证顺序执行的场景,并且只有一个线程在执行

解释一下线程池的核心参数,线程池的执行过程?

核心参数:corepoolsize 核心线程数

maximunpoolsize 线程池最大数量

keepalivetime 多余空闲线程的存活时间

unitime 时间单位

workQueue 工作队列

threadFactory 线程工厂

handler. 拒绝策略

执行过程:1.提交任务后先与核心线程数对比,

2.小于核心线程数创建核心线程

3.大于核心线程数判断阻塞队列是否已满

4.阻塞队列未满将任务添加到阻塞队列中

5.阻塞队列满创建非核心线程执行任务

6.若非核心线程创建失败,--拒绝任务

如果提交任务时,线程池队列已满,这时候会发生什么?

线程池线上参数如何优化?

1.首先需要知道,功能最大并发量,单任务处理时长,系统允许任务最大的响应时长

2.然后每个核心参数都有个计算公式,具体网上可以查到。

分布式篇

分布式理论

说说你对CAP理论的理解?

1.一致性,可用性,分区容忍性。

说说你用过的注册中心,分别使用了什么模型?(AP,CP)

eureka--AP模型 zookeeper--CP模型

说说你对BASE理论的理解?

我觉得就是保证p的情况下,根据功能业务的特点来补全A或C,属于非百分百保证的措施

分布式事务相关

如何解决分布式事务问题?你用过哪些解决分布式事务的方案?

说一下对2PC,3PC协议的理解?

有没有用过SEATA,SEATA的实现过程是什么?

如何基于MQ实现最终一致性?

实战篇

如何设计接口并保证他们的安全?

如何快速定位CPU溢出?

如何设计实现一个限流组件?

如何让系统能抗住预约抢购活动的流量压力?

histrix的实现原理

hystrix实现的功能有 熔断,降级处理,资源隔离,缓存,常用的为前三个,

资源隔离:分布式系统中,不同服务的线程隔离和信号量隔离,同一个调用链中某一个服务调用问题不会影响其他服务的调用

降级机制:资源不足时和超时时调用降级处理方法,返回托底数据。

熔断:请求连续失败大于阈值时,断路器开启,指定时间后断路器转为半开状态,半开状态下,若请求成功数大于阈值,断路器关闭

缓存:返回结果缓存,后续相同请求时,直接返回缓存数据

隔离模式:线程池隔离和信号量隔离

histrix openfegin rebbon超时的配置方案?

feign的调用超时时间和ribbon的超时时间只会有一个生效,feign优先,ribbon的超时时间时默认1s

由于connection的时间一般很短,所以忽略只要 ribbon的重试次数*读取时间小于hystrix的超时时间就可以了

(1 + MaxAutoRetries) * (1 + MaxAutoRetriesNextServer)* ReadTimeOut < hystrix 的 *timeoutInMilliseconds

如何指定服务的调用超时时间?

feign.client.config.default(课替换成指定服务名称).xxxTimeout

如果出现cpu内存告警,如何定位问题并解决

使用top指令找出cpu占用最高的pid

可以用 jmap -heap PID 查看是否内存分配过小

jmap -histo:live PID | more查看最占内存的对象

有没有用过线程池处理多线程的场景

动态代理的原理及常见应用

原理:分为(JDK 动态代理 和 cglib 动态代理)

jdk动态代理:实现了 invocationHandler接口 通过调用invoke方法访问目标方法 本质就是反射机制的应用

常见应用:AOP 的实现、RPC 远程调用、Java 注解对象获取、日志框架、全局性异常处理、事务处理


eureka:服务注册中心,同一管理注册的服务,

服务注册:分布式场景下,一个服务有多个ip+端口,交给nginx管理会频繁修改配置文件,而且不灵活,引入注册中心,将统一服务的不同ip用服务名管理起来

服务发现:当有服务启动后,服务会自动向注册中心发起注册请求

幂等的实现?高并发下?防止超卖

1.每次更新数据库之前查询数据库,并启用cas乐观锁的方式(查询的时候查一个版本号,更新的时候也更新版本+1)

arrayList底层和 扩容机制

实现自 Collection下的List类 底层由数组组成,扩容时一般以1.5倍创建新数组,在将原数组复制到心数组,原数组交由gc自动回收。

springmvc工作流程

dispatcherServlet-》handlerMapping-handleExcutorChain->HandleAdpter-Handler-ModleAndView->试图解析器-view->渲染视图-返回用户

jvm:

jvm分区?

1.线程私有内存区:程序计数器,java虚拟机栈(线程私有的存放栈帧),本地方法栈(为非java方法提供服务)

2.线程共享内存区:堆(新生代,老年代),方法区(存放静态变量,常量,类名等)

项目中遇到的困难?

消息队列的消息丢失-》在项目首次用到消息队列处理大量数据接收的时候,我们使用了消息队列来对消息解析和消息入库做了一个解藕的操作,但是运行一段时间后,发现了生产环境存在数据丢失的情况,我们紧急定位,联系了数据上层推送房,发现每次丢失的数据都是在迭代发布,也就是服务重启的时候,猜测是消息消费时,由于服务重启,导致消息丢失,而且也没有相应日志报错,

做了如下措施,

1,开启应用的优雅停机模式,设置间隔时间为30s。

2,服务生产者队列开启持久化,

3,并开启消息消费确认机制,

4,再设置上死信队列,

5,并且开启一个另一个消费者,消费死信队列的消息

6,失败的消息存放到数据库中

7,定时任务定时调用生产者将消息重新推送至消息队列

新技术的应用分表分库-》在数据源切换的过程中,使用到了新技术shardingspherejdbc,相同部门没有其他人使用过,只能通过查询官方文档尝试使用,在调试的过程中,出现了如何在一个服务中兼容 shardingsphere和mycat两个数据源?如何设置默认访问的库?如何自定义多个分裤规则并灵活应用在不同的表中?如何配置读写分离?最终都是通过查询官方文档,(像默认的库,读写分离配置,自定义多个芬片规则并灵活应用等问题,官方文档都没有给出解答,是在自己的猜测尝试,查看源码和查询网上其他人的解决方案来解决的)

nginx:

线程的阻塞方式?

线程由五种生命状态:创建、就绪、运行、阻塞、死亡

三种阻塞方式?

sleep在等待指定时间后,会重新进入等待状态继续争抢资源,sleep在等待期间不会释放锁资源

wait,会释放锁,只有在持有锁资源的线程调用notify或notifyAll才会让wait的线程继续就绪状态

同步阻塞。当多个线程想获取同一个锁资源,且锁资源正在被占用的情况下,其他线程会被JVM放入锁池中等待

sleep和wait的区别?

sleep等待一定时间后自动进入运行状态,期间不会释放锁,而wait是会释放🔒进入等待状态,只有当被notify或notifyAll时才会进入就绪状态

  1. HashMap什么时候分配内存空间

第一次put的时候。

  1. HashMap内部的bucket数组长度为什么一直都是2的整数次幂

寻址的方式是(table.length - 1) & key.hash();而hash中的算法为(h = key.hashCode()) ^ (h >>> 16)

最终减少了hash碰撞,而且通过位运算符寻址效率更高,table的长度一般时2的整数幂类似000100000这样的数-1后变成了000011111

  1. HashMap默认的bucket数组是多大
  2. HashMap什么时候开辟bucket数组占用内存
  3. HashMap何时扩容?
  4. 桶中的元素链表何时转换为红黑树,什么时候转回链表,为什么要这么设计?
  5. Java 8中为什么要引进红黑树,是为了解决什么场景的问题?
  6. HashMap如何处理key为null的键值对?

hashmap的扩容机制?

1.当HashMap中存储的元素大小等于桶数组大小乘以负载因子的时候整个HashMap就要扩容

2.

mysql主从同步的方式?

数据库的悲观锁是行还是表锁?

线程执行过程中出现异常会做什么操作?

所有设计模式的实现方式?

jdk1.8lamd表达式常见应用?

自旋锁的原理?

基于cas实现的一种锁,包含

aop和ioc的理解?

aop是动态代理模式,ioc是工厂模式,底层都用到了反射机制

aop是一种编程理念,面向切面编程,ioc时spring的bean管理机制

aop有几个重要概念:连接点,切入点,通知,切面,引入

@bean的生命周期?

分为6个阶段:bean定义,实例化,属性赋值,初始化,生存期,销毁

自动注入的原理?

核心注解EnableAutoConfiguration,通过读取spring。factory文件加载xxxAutoConfig,来自动加载对应的业务类

而我们定义的@Service,@Controller@Component类都是由ComponentScan扫描加载。

springboot启动流程?

一 springApplication构造函数的工作

1.确定应用类型 WebApplicationType.deduceFromClasspath

2.加载所有初始化器从 META-INF/spring.factories,也可以自己实现ApplicationContextInitializer接口自定义初始化器

3.加载所有监听器

4.deduceMainApplicationClass();确定main方法所在类为后续包扫描做准备。

二run方法

1.开启计时器(用于打印出启动耗时)

2.获取并启用监听器

3.设置启动参数

4.准备环境变量

5.忽略bean信息configureIgnoreBeanInfo()

6.打印banner

7.创建应用程序上下文 createApplicationContext() 反射的方式创建context

8.准备上下文环境(实力化beanname生成器,执行初始化器,注册启动参数至容器中)

springcloudgateway的过滤器实现方式?执行顺序?

可以实现globalgatewayfilter和自定义gatewayfilter

order越小越靠前,没有order全局优先,安配置文件配置顺序

了解过网络编程吗?

定时任务怎么实现?

可以使用enableschaule然后用注解schaule定义定是任务方法,可以呀单独写一个服务通过linux的cron实现

了解雪花算法吗?

由1+41+5+5+12 组成 分别为 0+时间戳+机器id+服务id+序号组成

令牌桶限流原理?

关联参数,桶长,令牌产生速率,过滤

springboot的循环依赖?

容器在启动的时候出现a依赖bb依赖cc依赖a的情况

使用懒加载

或者使用setter注入,使用时注入

对自旋锁的季节?

线程问题1:哲学家就餐问题?

使用面向对象的思维,先构建两个对象,筷子:编号,哲学家:左手筷子,右手筷子,编号。然后创建线程的时候混入一个左撇子,或者混入一半左撇子。

线程问题2:线程交替问题,两个线程(字母,数字),循环输出A1B2C3......Z26;

可以采用juc包中的 lockSupport类实现。

使用transferQueue同步队列实现

最重要:使用syncronized单锁wait和notify实现,,若要制定先打印的顺序可以使用,countdownLatch

如果需要打印类似Aa1Bb2,可以使用reentryLock ,lock.newCondition,或者用lockSupport.park

线程问题3:生产者消费者问题,实现一个队列,同步队列,实现线程安全的put get方法

线程问题4:异步回调回滚问题(分布式事务)

线程问题5:底层同步问题(乱序和屏障)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值