leetcode java 大厂基础面试题附答案(四)

目录

1. 说一下泛型原理,并举例说明。(京东)

2. 讲下 Kafka、RabbitMQ、RocketMQ 之间的区别是什么?(京东)

3. 介绍下 MySQL 聚簇索引与非聚簇索引的区别(InnoDB 与 Myisam 引擎)?(京东)

4. SpringAOP 底层原理(美团)

5. HashMap 的扩容机制是怎样的?(美团)

6. ConcurrentHashMap 的存储结构是怎样的?(美团)

7. 线程池大小如何设置?(美团)

8. G1 收集器有哪些特点?(美团)

9. 有哪些手段来排查 OOM 的问题?(美团)

10. B+ 树的叶子节点链表是单向还是双向?(美团)

11. MVCC 是什么?它的底层原理是什么?(美团)


1. 说一下泛型原理,并举例说明。(京东)


泛型就是将类型变成参数传入,使得可以使用的类型多样化,从而实现解耦。Java 泛型是在 Java1.5 以后出现的,为保持对以前版本的兼容,使用了擦除的方法实现泛型。擦除是指在一定程度无视类型参数 T,直接从 T 所在的类开始向上 T 的父类去擦除,如调用泛型方法,传入类型参数 T 进入方法内部,若没在声明时做类似 publicTmethodName(TextendsFathert){}, Java 就进行了向上类型的擦除,直接把参数t当做 Object 类来处理,而不是传进去的 T。即在有泛型的任何类和方法内部,它都无法知道自己的泛型参数,擦除和转型都是在边界上发生,即传进去的参在进入类或方法时被擦除掉,但传出来的时候又被转成了我们设置的 T。在泛型类或方法内,任何涉及到具体类型(即擦除后的类型的子类)操作都不能进行,如 newT(),或者 T.play()(play 为某子类的方法而不是擦除后的类的方法)。


2. 讲下 Kafka、RabbitMQ、RocketMQ 之间的区别是什么?(京东)


性能
消息中间件的性能主要衡量吞吐量,Kafka 的吞吐量比 RabbitMQ 要高出 1~2 个数量级,RabbitMQ 的单机 QPS 在万级别,Kafka 的单机 QPS 能够达到百万级别。RocketMQ 单机写入 TPS 单实例约 7 万条/秒,单机部署 3 个Broker,可以跑到最高 12 万条/秒,消息大小 10 个字节,Kafka 如果开启幂等、事务等功能,性能也会有所降低。
数据可靠性
Kafka 与 RabbitMQ 都具备多副本机制,数据可靠性较高。RocketMQ 支持异步实时刷盘,同步刷盘,同步 Replication,异步 Replication。服务可用性 Kafka 采用集群部署,分区与多副本的设计,使得单节点宕机对服务无影响,且支持消息容量的线性提升。RabbitMQ 支持集群部署,集群节点数量有多种规格。RocketMQ 是分布式架构,可用性高。
功能
Kafka 与 RabbitMQ 都是比较主流的两款消息中间件,具备消息传递的基本功能,但在一些特殊的功能方面存在差异,RocketMQ 在阿里集团内部有大量的应用在使用。


3. 介绍下 MySQL 聚簇索引与非聚簇索引的区别(InnoDB 与 Myisam 引擎)?(京东)


聚集索引是指数据库表行中数据的物理顺序与键值的逻辑(索引)顺序相同。一个表只能有一个聚簇索引,因为一个表的物理顺序只有一种情况,所以,对应的聚簇索引只能有一个。聚簇索引的叶子节点就是数据节点,既存储索引值,又在叶子节点存储行数据。
Innodb 创建表后生成的文件有:
frm:创建表的语句;
idb:表里面的数据+索引文件非聚集索引(MyISAM引擎的底层实现)的逻辑顺序与磁盘上行的物理存储顺序不同。非聚簇索引的叶子节点仍然是索引节点,只不过有指向对应数据块的指针。索引命中后,需要回表查询。
Myisam 创建表后生成的文件有:
frm:创建表的语句 MYD:表里面的数据文件(myisam data)
MYI:表里面的索引文件(myisam index)
innodb 的次索引指向对主键的引用(聚簇索引)
myisam 的次索引和主索引都指向物理行(非聚簇索引)


4. SpringAOP 底层原理(美团)


aop 底层是采用动态代理机制实现的:接口+实现类
- 如果要代理的对象,实现了某个接口,那么 SpringAOP 会使用 JDKProxy ,去创建代理对象。
- 没有实现接口的对象,就无法使用JDKProxy去进行代理了,这时候 SpringAOP 会使用 Cglib 生成一个被代理对象的子类来作为代理


5. HashMap 的扩容机制是怎样的?(美团)


一般情况下,当元素数量超过阈值时便会触发扩容。每次扩容的容量都是之前容量的 2 倍。HashMap 的容量是有上限的,必须小于 1<<30,即 1073741824。如果容量超出了这个数,则不再增长,且阈值会被设置为 Integer.MAX_VALUE。
JDK7 中的扩容机制:
- 空参数的构造函数:以默认容量、默认负载因子、默认阈值初始化数组。内部数组是空数组。
- 有参构造函数:根据参数确定容量、负载因子、阈值等。
- 第一次 put 时会初始化数组,其容量变为不小于指定容量的2的幂数,然后根据负载因子确定阈值。
- 如果不是第一次扩容,则新容量=旧容量x2,新阈值=新容量x负载因子。
JDK 8的扩容机制:
- 空参数的构造函数:实例化的 HashMap 默认内部数组是 null,即没有实例化。第一次调用 put 方法时,则会开始第一次初始化扩容,长度为 16。
- 有参构造函数:用于指定容量。会根据指定的正整数找到不小于指定容量的 2 的幂数,将这个数设置赋值给阈值(threshold)。第一次调用 put 方法时,会将阈值赋值给容量,然后让阈值=容量x负载因子。
- 如果不是第一次扩容,则容量变为原来的 2 倍,阈值也变为原来的 2 倍。(容量和阈值都变为原来的 2 倍时,负载因子还是不变)。
此外还有几个细节需要注意:
- 首次 put 时,先会触发扩容(算是初始化),然后存入数据,然后判断是否需要扩容;
- 不是首次 put,则不再初始化,直接存入数据,然后判断是否需要扩容;


6. ConcurrentHashMap 的存储结构是怎样的?(美团)


Java7 中 ConcurrnetHashMap 使用的分段锁,也就是每一个 Segment 上同时只有一个线程可以操作,每一个 Segment 都是一个类似 HashMap 数组的结构,它可以扩容,它的冲突会转化为链表。但是 Segment 的个数一但初始化就不能改变,默认 Segment 的个数是 16 个。
Java8 中的 ConcurrnetHashMap 使用的 Synchronized 锁加 CAS 的机制。结构也由 Java7 中的 Segment 数组+ HashEntry 数组+链表进化成了 Node 数组+链表/红黑树,Node 是类似于一个 HashEntry 的结构。它的冲突再达到一定大小时会转化成红黑树,在冲突小于一定数量时又退回链表


7. 线程池大小如何设置?(美团)


CPU 密集型任务 (N+1):这种任务消耗的主要是 CPU 资源,可以将线程数设置为 N(CPU核心数)+1,比 CPU 核心数多出来的一个线程是为了防止线程偶发的缺页中断,或者其它原因导致的任务暂停而带来的影响。一旦任务暂停,CPU 就会处于空闲状态,而在这种情况下多出来的一个线程就可以充分利用 CPU 的空闲时间。
I/O 密集型任务 (2N):这种任务应用起来,系统会用大部分的时间来处理 I/O 交互,而线程在处理 I/O 的时间段内不会占用 CPU 来处理,这时就可以将 CPU 交出给其它线程使用。因此在 I/O 密集型任务的应用中,我们可以多配置一些线程,具体的计算方法是 2N


8. G1 收集器有哪些特点?(美团)


- G1 的全称是 Garbage-First,意为垃圾优先,哪一块的垃圾最多就优先清理它。
- G1 GC 最主要的设计目标是:将 STW 停顿的时间和分布,变成可预期且可配置的。被视为 JDK1.7 中 HotSpot 虚拟机的一个重要进化特征。它具备一下特点:
- 并行与并发:G1 能充分利用 CPU、多核环境下的硬件优势,使用多个 CPU(CPU 或者 CPU 核心)来缩短 Stop-The-World 停顿时间。部分其他收集器原本需要停顿 Java 线程执行的 GC 动作,G1 收集器仍然可以通过并发的方式让 java 程序继续执行。
- 分代收集:虽然 G1 可以不需要其他收集器配合就能独立管理整个 GC 堆,但是还是保留了分代的概念。
- 空间整合:与 CMS 的“标记-清理”算法不同,G1 从整体来看是基于“标记-整理”算法实现的收集器;从局部上来看是基于“标记-复制”算法实现的。
- 可预测的停顿:这是 G1 相对于 CMS 的另一个大优势,降低停顿时间是 G1 和 CMS 共同的关注点,但 G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内。
G1 收集器在后台维护了一个优先列表,每次根据允许的收集时间,优先选择回收价值最大的 Region(这也就是它的名字 Garbage-First 的由来)


9. 有哪些手段来排查 OOM 的问题?(美团)


- 增加两个参数 -XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/tmp/heapdump.hprof,当 OOM 发生时自动 dump 堆内存信息到指定目录。
- 同时 jstat 查看监控 JVM 的内存和 GC 情况,先观察问题大概出在什么区域。
- 使用 MAT 工具载入到 dump 文件,分析大对象的占用情况,比如 HashMap 做缓存未清理,时间长了就会内存溢出,可以把改为弱引用


10. B+ 树的叶子节点链表是单向还是双向?(美团)


双向链表


11. MVCC 是什么?它的底层原理是什么?(美团)


MVCC,多版本并发控制,它是通过读取历史版本的数据,来降低并发事务冲突,从而提高并发性能的一种机制。事务版本号、表的隐藏列、undolog 和 readview。

参考:
链接:https://leetcode.cn/leetbook/read/da-han-hou-duan-gang-ti-mu-he-ji-shang/nim2qr/
 

猜你喜欢

转载自blog.csdn.net/lejian/article/details/129372914