Java Interview

Posted by Justin Ling Mao on October 27, 2020

Java Interview

集合

HashMap

  • Put 首先,根据key,经过自定义的hash算法计算,得到一个hash值,再通过这个hash值&(table.length-1)得到在数组中的index。 然后通过索引index获取到数组中对应索引处的链表。拿到链表遍历里面的节点,如果没找到与要插入的节点具有相同key的节点,那么直接在链表中插入一个新的节点。 如果找到了与要插入的节点具有相同key的节点,那么就把原有的value进行覆盖。
  • Get Resize扩容 头插法 vs 尾插法 Hash碰撞: 开放地址法(核心思想:探测地址) 所谓开放地址法就是发生冲突时在散列表(也就是数组里)里去寻找合适的位置存取对应的元素。 1、线性探测法 最容易想到的就是当前位置冲突了,那我就去找相邻的下一个位置 问题:随着键值对的增多,会在哈希表里形成连续的键值对. 这样的话,当插入元素时,任意一个落入这个区间的元素都要一直探测到区间末尾,并且最终将自己加入到这个区间内。 这样就会导致落在区间内的关键字Key要进行多次探测才能找到合适的位置,并且还会继续增大这个连续区间,使探测时间变得更长,这样的现象被称为”一次聚集” 2、平方探测法 我们可以在探测时不一个挨着一个地向后探测,我们可以跳跃着探测,这样就避免了一次聚集。 其实我们可以让它按照 i^2 的规律来跳跃探测 虽然平方探测法解决了线性探测法的一次聚集,但是它也有一个小问题,就是关键字key散列到同一位置后探测时的路径是一样的。这种现象出现的原因是由于对于落在同一个位置的关键字我们采取了一个依赖 i 的函数(i或者i^2)来进行探测,它不会因为关键字的不同或其他因素而改变探测的路径。那么我们是不是可以让探测的方法依赖于关键字呢? 3、双散列 我们可以再弄另外一个Hash函数(共两个散列函数: hash1(); hash2()),对落在同一个位置的关键字进行再次的Hash,探测的时候就用依赖这个Hash值去探测
    链表法:

JVM

不仅如此,还可以使用 String 的 intern() 方法在运行过程将字符串添加到 String Pool 中。 当一个字符串调用 intern() 方法时,如果 String Pool 中已经存在一个字符串和该字符串值相等(使用 equals() 方法进行确定),那么就会返回 String Pool 中字符串的引用;否则,就会在 String Pool 中添加一个新的字符串,并返回这个新字符串的引用。

存在继承的情况下,初始化顺序为:

父类(静态变量、静态语句块) 子类(静态变量、静态语句块) 父类(实例变量、普通语句块) 父类(构造函数) 子类(实例变量、普通语句块) 子类(构造函数)

Object 通用方法: hashcode,equal, wait, notify(All), finalize, toString, clone

ConcurrentModificationException???

本地消息表 本地消息表与业务数据表处于同一个数据库中,这样就能利用本地事务来保证在对这两个表的操作满足事务特性,并且使用了消息队列来保证最终一致性。

在分布式事务操作的一方完成写业务数据的操作之后向本地消息表发送一个消息,本地事务能保证这个消息一定会被写入本地消息表中。 之后将本地消息表中的消息转发到消息队列中,如果转发成功则将消息从本地消息表中删除,否则继续重新转发。 在分布式事务操作的另一方从消息队列中读取一个消息,并执行消息中的操作。

ThreadLocal 偏向锁和轻量级锁

computeIfAbsent

第一二三范式=mysql

Java问题 1、jvm:运行时数据区、垃圾收集算法、垃圾收集器(CMS,G1)、年轻代老年代垃圾回收机制,GCRoot,线上调优 双亲委派机制、破坏双亲委派机制 2、集合:hashMap、hashTable 、ConcurrentHashMap区别,1.7 1.8的区别,put/get过程 3、Java锁的升级过程,底层原理,synchronize和lock的区别,CAS运行过程,轻量级锁和重量级锁的区别 4、AQS:底层实现原理,CountDownLatch CyclicBarrier、Semaphore底层实现,公平锁和非公平锁的底层实现 5、ThreadLocal的应用原理,内部弱引用,导致内存泄漏怎么解决 6、线程池的类型,执行过程,线程池的状态,怎么判断线程池中线程的活跃数,你们用的什么类型的线程池? 用的什么类去创建的线程池,ThreadPoolExecutor和Executors创建池的区别,线程池执行的方法:submit和execute 这个两个方法的区别 7、线程的状态以及他们状态的转换,sleep和wait的区别 8、内存一致性问题:happen-before,volatile怎么保证可见性和有序性的,内存模型

spring问题 IOC AOP说一下,看过源码吗? 循环依赖的问题能解决吗(set注入,构造函数注入,单例和多例模式那些可以解决循环依赖那些不幸),动态代理(jdk和cglib)的区别 事务注解,什么情况下会失效?传播机制你了解吗?失效的原因你知道吗? 一个请求过来spring内部执行过程?怎么记性解析参数的?拦截器和过滤器是在哪个阶段进行解析的,拦截器和过滤器的区别 springboot问题 springboot启动的核心注解? spring和springboot区别? 自动装配的原理,装配过程? 怎么自定义一个starter启动器?

mysql问题

常用的存储引擎 mysql一个表最多支持多少个索引? Innodb和MyIsm的区别 innodb底层索引的结构,多路平衡这个多的大小是?16kb,为什么是16 B+树的存储数据的结构,主键索引和非主建索引的区别,涉及到回表查询和覆盖索引 聚簇索引和非聚簇索引的区别 数据库优化做过吗,都有哪些 索引优化了解吗,都有哪些 事务隔离级别,会产生什么问题 脏读,重复读,幻读是什么?怎么解决 mvcc是什么,底层原理是什么? 一条更新语句涉及到哪些步骤,涉及到事务提交回滚,redo undo日志 数据库的锁有哪些,间隙锁,nextkey锁 给你一条sql语句你分析出他上的什么锁吗,需要考虑语句中条件字段是什么索引,多种情况 数据库的死锁,四个必要条件,什么情况会产生死锁,你能举个例子吗

LSM vs b+ tree对比

Redis问题

哪几种数据类型?你们用到过哪些数据类型?他们底层实现原理? 为什么那么快? 和数据库的一致性问题? 线程模型? 内存管理? 淘汰策略? 主从同步?持久化机制?持久化在配置文件中的配置 集群:哨兵原理,集群原理,添加/删除新集群节点?(单节点只能保证十万的并发) 分布式锁?锁续约问题? 缓存雪崩,缓存击穿、缓存穿透和布隆过滤器的解决

Redis集群方式, 共有三种: 主从模式,哨兵模式,cluster(集群)模式 1 2 3 主从模式:是三种集群方式里最简单的。它主要是基于Redis的主从复制特性架构的。通常我们会设置一个主节点,N个从节点;默认情况下,主节点负责处理使用者的IO操作, 而从节点则会对主节点的数据进行备份,并且也会对外提供读操作的处理。主要的特点如下:

主从模式下,当某一节点损坏时,因为其会将数据备份到其它Redis实例上,这样做在很大程度上可以恢复丢失的数据。

主从模式下,可以保证负载均衡,这里不再叙说了

主从模式下,主节点和从节点是读写分离的。使用者不仅可以从主节点上读取数据,还可以很方便的从从节点上读取到数据,这在一定程度上缓解了主机的压力。

从节点也是能够支持写入数据的,只不过从从节点写入的数据不会同步到主节点以及其它的从节点下。

从以上,我们不难看出Redis在主从模式下,必须保证主节点不会宕机——一旦主节点宕机,其它节点不会竞争称为主节点,此时,Redis将丧失写的能力。这点在生产环境中,是致命的。 哨兵原理: 哨兵模式在一定程度上能够帮我们规避掉一些意外(服务器宕机,停电,硬件损坏)导致的灾难性后果。其实,哨兵模式的核心还是主从复制。只不过相对于主从模式在主节点宕机导致不可写的情况下,多了一个竞选机制——从所有的从节点竞选出新的主节点。竞选机制的实现,是依赖于在系统中启动一个sentinel进程。

sentinel特点:

监控:它会监听主服务器和从服务器之间是否在正常工作。

通知:它能够通过API告诉系统管理员或者程序,集群中某个实例出了问题。

故障转移:它在主节点出了问题的情况下,会在所有的从节点中竞选出一个节点,并将其作为新的主节点。

提供主服务器地址:它还能够向使用者提供当前主节点的地址。这在故障转移后,使用者不用做任何修改就可以知道当前主节点地址。 哨兵模式下的故障迁移#

主观下线 哨兵(Sentinel)节点会每秒一次的频率向建立了命令连接的实例发送PING命令,如果在down-after-milliseconds毫秒内没有做出有效响应包括(PONG/LOADING/MASTERDOWN)以外的响应,哨兵就会将该实例在本结构体中的状态标记为SRI_S_DOWN主观下线 客观下线 当一个哨兵节点发现主节点处于主观下线状态是,会向其他的哨兵节点发出询问,该节点是不是已经主观下线了。如果超过配置参数quorum个节点认为是主观下线时,该哨兵节点就会将自己维护的结构体中该主节点标记为SRI_O_DOWN客观下线 询问命令SENTINEL is-master-down-by-addr Leader选举 在认为主节点客观下线的情况下,哨兵节点节点间会发起一次选举,命令还是上面的命令SENTINEL is-master-down-by-addr ,只是run_id这次会将自己的run_id带进去, 希望接受者将自己设置为主节点。如果超过半数以上的节点返回将该节点标记为leader的情况下,会有该leader对故障进行迁移 优缺点 优点 高可用,在主节点故障时能实现故障的转移 缺点:Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。

集群原理: Redis 集群的优势:

自动分割数据到不同的节点上。

整个集群的部分节点失败或者不可达的情况下能够继续处理命令。

Redis 集群的数据分片 Redis 集群没有使用一致性hash, 而是引入了 哈希槽的概念.

Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么:

节点 A 包含 0 到 5500号哈希槽.

节点 B 包含5501 到 11000 号哈希槽.

节点 C 包含11001 到 16384号哈希槽. 集群模式和哨兵模式的区别# 哨兵模式监控权交给了哨兵系统,集群模式中是工作节点自己做监控 哨兵模式发起选举是选举一个leader哨兵节点来处理故障转移,集群模式是在从节点中选举一个新的主节点,来处理故障的转移 redis的哨兵模式基本已经可以实现高可用,读写分离 ,但是在这种模式下每台redis服务器都存储相同的数据,很浪费内存,所以在redis3.0上加入了cluster模式,实现的redis的分布式存储,也就是说每台redis节点上存储不同的内容。

Redis-Cluster采用无中心结构,它的特点如下:

所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。

节点的fail是通过集群中超过半数的节点检测失效时才生效。

客户端与redis节点直连,不需要中间代理层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。 为了保证高可用,redis-cluster集群引入了主从模式,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点。当其它主节点ping一个主节点A时, 如果半数以上的主节点与A通信超时,那么认为主节点A宕机了。如果主节点A和它的从节点A1都宕机了,那么该集群就无法再提供服务了

其他一些不敢兴趣的话题

rabbitMQ问题 rabbitMQ的作用?好处和坏处? 消息丢失怎么解决?消息重复怎么解决?消息积压怎么解决?消息怎么保证顺序执行?