【每日一面】day 1

【Tips】每日一“面”专栏从今天开始更新~

  • 每日一面的素材来自于牛客的面经分享,多为中大厂的面经,实习、校招均有涉及,且经过个人挑选与整理的较为经典的问题。
  • 回答则来自于个人总结与AI工具,但不是存粹的AI生成就贴上来了,是经过整理的。
  • 另外这里的每天不是完整了一套面试题(因为每天一套面经整理的话,强度太高了…我还有其他事要忙hhh)
  • 这一个专栏应该会持续更新到明年的一月…

Q:jdk1.8之前hashmap插入时为啥使用头插法,还让我解释hashmap因为头插法出现死循环是怎么出现的?

具体来说,在发生哈希冲突时,即多个键值对映射到了同一个桶(bucket)上,这些键值对会以链表的形式链接起来。当采用头插法时,新来的元素直接被放置在链表的头部,这样做的好处是:

  1. 插入效率高:每次插入都是在链表头部进行,因此不需要遍历链表。
  2. 代码实现简单:头插法实现逻辑相对简单,易于理解和维护

头插法出现死循环:

  1. 并发修改:当两个或多个线程几乎同时尝试向HashMap中添加元素,并且这些元素正好哈希到了同一个桶(bucket)上时,就可能发生问题。
  2. 链表结构改变:在头插法下,每次新插入的节点都会被放在链表头部。如果两个线程都试图在相同的桶内插入新的元素,那么它们会各自创建一个新的头节点,并尝试更新桶中的引用指向新的头节点。
  3. 竞争条件:假设线程A和线程B都在没有正确同步的情况下执行了以下步骤:
    • 线程A读取了旧的头节点。
    • 线程B也读取了旧的头节点。
    • 线程A创建了一个新节点并将其设置为头节点。
    • 线程B创建了自己的新节点,但是由于它看到的是已经被线程A更改过的头节点,它将它的新节点链接到由线程A创建的新节点之后。
    • 如果此时线程A再次访问这个桶,并且它的新节点意外地指向了线程B的新节点,就会形成一个闭环(环形链表)。
  4. 死循环:一旦形成了这样的环形链表,后续遍历该链表的操作将会陷入无限循环,因为遍历器无法到达链表的末尾。

为了防止这种问题的发生,在Java 8中,对于HashMap的实现进行了改进,不仅改变了插入方式从头插法改为尾插法,而且引入了红黑树来优化长链表的性能。此外,还提供了线程安全的替代方案如ConcurrentHashMap,它通过分段锁等机制来支持高效的并发访问。如果你的应用需要处理并发情况,建议使用ConcurrentHashMap而不是普通的HashMap。

Q:spring里面是怎么知道这个bean是单例的

使用ApplicationContext 如果你有访问到ApplicationContext的引用,可以通过isSingleton方法来判断一个Bean是否是单例。

ApplicationContext context = ...; // 获取到你的ApplicationContext
boolean isSingleton = context.isSingleton("beanName");

或者

ApplicationContext context = ...; // 获取到你的ApplicationContext
BeanDefinition beanDefinition = ((ConfigurableApplicationContext) context).getBeanFactory().getBeanDefinition("beanName");
String scope = beanDefinition.getScope();
boolean isSingleton = "singleton".equals(scope);

Q:jvm中怎么消除STW

STW,即 Stop The World ,指触发Full GC时除了垃圾回收相关线程,其他线程一律停滞

使用低停顿时间的垃圾回收器:

  • G1垃圾回收器:适用于大内存应用,具有可调节的停顿时间,可以在后台工作,尽量减少应用程序的停顿时间。
  • ZGC(Z Garbage Collector)Shenandoah:这两个垃圾回收器设计目标是实现低停顿时间,适合大规模内存应用。

优化堆内存设置

  • 根据应用的需求合理调整堆的初始大小和最大大小,避免频繁的GC。
  • 使用合适的年轻代和老年代比例,以减少GC的次数和时间。

进行并发垃圾回收

  • 使用并发的垃圾回收策略,例如G1中的并发标记阶段,允许应用线程在大多数GC阶段并行执行,减少整体停顿时间。

减少对象创建

  • 通过对象池等设计模式复用对象,减少GC的压力,降低STW事件的频率。
  • 优化代码逻辑,避免创建大量短命对象。

调整GC参数

  • 通过JVM启动参数调整GC的行为,例如设置-XX:MaxGCPauseMillis以限制GC的最大停顿时间。
  • 使用-XX:+UseStringDeduplication来减少字符串的重复存储,从而降低内存使用。

监控和调优

  • 使用JVM提供的监控工具(如VisualVM、JConsole、GC日志)监控GC行为,分析GC的时间和频率,依据数据进行优化。

Q:你了解哪些确保数据库与缓存一致性的算法

这个缓存一致性场景其实很常见,比如类似的操作系统里Cache 和 主存的缓存一致性。

  1. 首先是最常见的**旁路缓存(Cache Aside)**策略:先访问缓存,如果没有再去访问数据库;写时,先更新数据库再删除缓存;
  2. 穿透写(Write Through),每次写操作都会同时写入缓存和数据库。
  3. 回写缓存(Write Back),首先写入缓存,缓存负责异步将数据更新回数据库。
  4. 延迟双删。更新数据库时,先删除缓存中的数据,然后更新数据库,等待一定时间后再次删除缓存。为了防止写操作期间有其他线程更新了缓存(在写入数据库后,重新读取旧数据),因此需要延时删

Q:MySQL的索引有哪些数据类型

  1. BTREE 索引:默认且最常用的索引类型,支持范围和精确查询。
  2. HASH 索引:用于精确查询,但不支持范围查询。
  3. FULLTEXT 索引:用于全文搜索,适合文本字段。
  4. SPATIAL 索引:用于地理信息的存储和查询。
  5. R-Tree 索引:用于多维空间数据的范围查询。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值