风离不摆烂学习日志Day20 Java 面经整理 金蝶社招面(偏业务)

Q: HashMap的实现原理

A:

HashMap是基于哈希表的Map接口的非同步实现。元素以键值对的形式存放,并且允许null键和null值,因为key值唯一(不能重复),因此,null键只有一个。另外,hashmap不保证元素存储的顺序,是一种无序的,和放入的顺序并不相同。HashMap是线程不安全的。

HashMap 的实例有两个参数影响其性能:初始容量和加载因子。容量是哈希表中桶的数量,初始容量只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。在Java编程语言中,加载因子默认值为0.75

HashMap由数组(键值对entry组成的数组主干)+ 链表(元素太多时为解决哈希冲突数组的一个元素上多个entry组成的链表)+ 红黑树(当链表的元素个数达到8链表存储改为红黑树存储)进行数据的存储。

Q: ConcurrentHashMap怎么实现线程安全的

A:

首先ConcurrentHashMap 是JUC包下的 HashMap的线程安全类 使用的是数组 加 链表 加 红黑树的方式实现,它是通过 CAS(CAS是英文单词Compare and Swap的缩写,翻译过来就是比较并替换) 或者 synchronized 来保证线程安全的,并且缩小了锁的粒度,查询性能也更高。

Q: 简述一下红黑树的数据结构

A:

红黑树的性质:

  • 每个节点不是红色就是黑色
  • 根节点为黑色
  • 没有连续的红色节点
  • 对于每个节点,每条路径上的黑色节点数相同

红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。

Q: 红黑树和平衡二叉树的区别

A:

红黑树和平衡二叉树区别如下:
1、红黑树放弃了追求完全平衡,追求大致平衡,在与平衡二叉树的时间复杂度相差不大的情况下,保证每次插入最多只需要三次旋转就能达到平衡,实现起来也更为简单。
2、平衡二叉树追求绝对平衡,条件比较苛刻,实现起来比较麻烦,每次插入新节点之后需要旋转的次数不能预知。

Q: 红黑树任意一个子节点到根节点的查询速度最多会差多少 (实际是问红黑树的最长路径和最短路径)

A:

最长路径最多是最短路径的两倍

Q: 谈谈对JUC并发包的理解

A:

JUC是java.util.concurrent包的简称,在Java5.0添加,目的就是为了更好的支持高并发任务。让开发者进行多线程编程时减少竞争条件和死锁的问题

常用的 atomic包 举个例子就是我们平时的 i++,不是原子的操作,在多线程环境下会发生错误,但是使用atomic提供的原子类,就可以很好的避免这个问题发生。

locks包

再比如 常用的异步任类 CompletableFutrue 也是JUC包下的

image-20230113112702635

Q: 谈谈对锁的理解

A:

  java中的锁机制是用来处理面对多线程并发情况下数据的一致性的。在我们操作一个对象或者调用一个方法前加锁,这样当其他线程也对该对象和方法进行访问时就需要获得锁,如果该锁被其他线程持有,那么该线程则进入阻塞队列等待获得锁。这样就保证了在同一时间只有一个线程在对该对象进行操作。

    java中的锁,从不同的角度有好几种划分,如:(悲观锁,乐观锁)、(公平锁,非公平锁)、(共享锁,独占锁)、(轻量级锁重量级锁)等。
    
    可重入锁
    在同一个函数内,一个线程如果已经在外层函数获得过一次锁,那么在内层函数该线程依旧可以获得另一把锁。java的可重入锁有:synchronized 和 ReentrantLock。

————————————————
版权声明:本文为CSDN博主「i总是学不会」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jh_554/article/details/126014153

Q: volatile怎么实现可见性和保障有序性

A:

https://blog.csdn.net/bfj11/article/details/123949405 八股文 贴链接了

Q: Java面向对象设计的五大原则

A:

(1)单一责任原则( Single Responsibility Principle, SRP)。
(2)开放-封闭原则(Open & Close Principle, OCP)。
(3)里氏替换原则(Liskov Substitution Principle,LSP)。
(4)依赖倒置原则(Dependence Inversion Principle,DIP)。
(5)接口分离原则( Interface Segregation Principle, ISP)。
————————————————

Q: 秒杀场景怎么设计

A:

Nginx 动静分离 保证动态请求打到服务器

秒杀链接加密

秒杀系统单一职责部署

秒杀读多写少 的场景做库存预热 提前准备好需要上架的商品 定时上架 用信号量控制写库

限流熔断降级

秒杀成功请求使用消息队列 扣减库存 创建订单

拦截恶意请求 在网关层

流量错峰 识别到频繁的 加验证码

多使用线程池和异步处理非主要业务

如何设计一个秒杀系统?

Q: 怎么解决订单超卖问题

A:

分布式锁

https://blog.csdn.net/u010391342/article/details/84372342?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-2-84372342-blog-120232331.pc_relevant_3mothn_strategy_and_data_recovery&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-2-84372342-blog-120232331.pc_relevant_3mothn_strategy_and_data_recovery&utm_relevant_index=5

比如悲观锁,分布式锁,乐观锁,队列串行化,Redis原子操作

Q: Redis实现分布式锁怎么避免死锁问题

A:

使用SET代替SETNX ,相当于SETNX+EXPIRE实现了原子性,不必担心SETNX成功,EXPIRE失败的问题! 有效的避免死锁!!!

Q: Redis实现分布式锁锁过期了,但业务还没有执行完,怎么办

A:

redisson给的答案是锁获取成功后,注册一个定时任务,每隔一定时间(this.internalLockLeaseTime / 3L)就去续约。internalLockLeaseTime可配置,默认30s。这种方式每次获取一个锁,就会创建一个定时任务,有些浪费

将续约的key的耗时保存在redis,再次获取锁时,直接使用上次耗时 + 10s 作为锁的过期时间, 不用每次都去续约。缺点:获取锁后->释放锁前,若每次执行耗时差距过大(业务方法的各条流程耗时差距过大),将得不到预期的效果

作者:老鼠AI大米_Java全栈
链接:https://www.jianshu.com/p/b3ac1407032a
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

https://www.jianshu.com/p/b3ac1407032a


Q: 谈谈对Nginx的了解

A:

Nginx是一款轻量级的Web服务器、反向代理服务器,由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用。 提供了 负载均衡 反向代理 缓存 等能力 我们一般在nginx.conf中配置路径映射 ssl等


Q: 负载均衡的策略有哪些

A:

1、轮询(默认)

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。

2、指定权重(常用)

指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。

3、IP绑定 ip_hash

每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。

4、fair(第三方)

按后端服务器的响应时间来分配请求,响应时间短的优先分配。

5、url_hash(第三方)

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。


Q: 数据库怎么优化

A:

建表规约 索引规约 SQL 语句 ORM 映射…


Q: 大批量下单请求冲击服务器怎么优化(可以从前端 后端 服务器部署配置等全方面聊)

A:

参照设计秒杀系统


Q: 谈谈单体应用和分布式架构的区别优缺点

A:

img