[1]. 数组(Array)和ArrayList的区别
数组是一种基本的数据结构,能够存储固定数量的、同一类型的数据项。数组在创建时就必须指定大小,一旦确定,其长度就不可更改。ArrayList是Java集合框架中的一个动态数组实现,它继承了List接口,可以自动调整大小。
数组可以存储基本数据类型和对象类型,ArrayList只能存储对象类型,对于基本类型需要使用它们的包装类。
[2]. 为什么数组的大小固定而Arraylist的大小可以动态改变?
数组在Java中被声明为一种对象,而且其大小在创建时就已经确定并分配了相应的内存。
ArrayList的大小可以动态改变是因为其底层数据结构是动态数组,并且实现了动态扩容机制。
[3]. Dijkstra算法的基本设计思想和适用场景
Dijkstra算法的基本设计思想是利用贪心策略和广度优先搜索(BFS)来求解单源最短路径问题。
适用于边权重非负的图,常用于求解道路网络、通信网络、计算机网络等领域中的最短路径问题。
[4]. Dijkstra算法的核心步骤
初始化:将起始节点到自身的距离设为0,其余节点到起始节点的距离设为无穷大,并将所有节点标记为未访问。
选择节点:从未访问的节点中选择当前距离起始节点最近的节点,并标记为已访问。
更新距离:对于选中的节点的每个邻居节点,如果通过该节点到达邻居节点的距离比当前已知的距离短,则更新该邻居节点的距离。
重复步骤:重复上述步骤,直到所有节点都被标记为已访问。
[5]. 解释一下什么是最短路径问题?
最短路径问题是指求解从图中的某个顶点出发到达另外一个顶点的所经过的边的权重和最小路径问题。
分为单源最短路径和任意两点之间的最短路径问题。
单源最短路径问题是求图中某一顶点到其他顶点的最短路径,任意两点之间的最短路径问题是求图中每一对结点间最短路径。
[6]. 模板模式与策略模式有何不同
模板模式和策略模式都是行为型设计模式。
模板模式是由抽象类来定义一个算法,在算法实现的不同步骤上由子类继承抽象方法并提供具体实现。策略模式是以接口形式提供抽象接口,由具体实现类提供不同算法。
模板模式一般只针对一套算法,注重对同一个算法的不同细节进行抽象提供不同的实现,而策略模式注重多套算法多套实现。
模板模式通过继承实现代码复用,而策略模式通过组合实现。
[7]. 如何解决Redis缓存击穿、缓存雪崩问题
缓存击穿是指并发查同一条数据,缓存雪崩是不同数据都同时过期了,导致很多数据都查不到从而查数据库。
缓存击穿的解决方法:
- 加互斥锁,保证同一时间只有一个业务线程更新缓存。
- 将热点数据设置为永不过期;
缓存雪崩的解决方法:
针对大量数据同时过期而引发的缓存雪崩问题,可以在设置缓存数据的过期时间时附加一个随机数,避免同时过期。
针对 Redis 故障宕机而引发的缓存雪崩问题:
- 启用服务熔断或请求限流机制;
- 利用Redis的哨兵模式或集群模式构建高可用的Redis服务。
[8]. 如何使用互斥锁来防止缓存击穿
- 检查缓存:首先检查缓存中是否存在数据。
- 获取锁:如果缓存中没有数据,则尝试获取互斥锁。
- 查询数据:获取锁成功后,查询数据库获取数据。
- 更新缓存:将查询到的数据写入缓存,并设置一个合理的过期时间。
- 释放锁:完成缓存更新后释放锁。
[9]. ConcurrentHashMap和HashMap的区别
HashMap是非线程安全的,ConcurrentHashMap是线程安全的。
HashMap适用于单线程环境或者不需要高并发访问的场景,ConcurrentHashMap适用于高并发环境。
[10]. ConcurrentHashMap中锁的粒度如何影响线程安全
在ConcurrentHashMap中,JDK1.7锁的粒度是基于Segment的,包含多个HashEntry,而JDK1.8锁的粒度就是HashEntry,降低了锁的粒度。
减少锁竞争:更细的锁粒度意味着在多线程访问时,锁定的数据范围更小,减少了锁竞争,提高了并发性能。
提高并发度:细粒度的锁允许更多线程同时操作不同的数据段,提高了ConcurrentHashMap的并发度。
[11]. ConcurrentHashMap中分段锁的概念
分段锁是在ConcurrentHashMap内部维护一个Segment数组,每个Segment都包含一个哈希表和一个锁。当执行写操作时,只需要锁定对应的Segment即可,而不会影响其他的Segment。
相较于 Hashtable 使用 synchronized 方法来保证线程安全,ConcurrentHashMap 采用分段锁的方式,在线程竞争激烈的情况下 ConcurrentHashMap 的效率要更高一些。