两个高频设计类面试题:如何设计HashMap和线程池

简介: 两个高频设计类面试题:如何设计HashMap和线程池

好,我是 yes。

最近在汇总面试题,但是我写的这个版本不是背诵版,不是那种死记硬背刻板的答案。

我的本意是抛砖引玉,针对每个题目给出我自己的理解和解释型的答案,然后背诵版本需要你们自行去总结和记忆。

因为八股文在面试中是一定要的,也就是该知道的题还是得知道的,而在理解的基础上记忆会比较深刻,并且可以应对一些变种问题。

但是不清楚这样的形式是不是受欢迎,所以我暂时拿两个题目先发出来看看反响。

所以如果觉得这样的形式哪里不好,需要改进的话,请留言。


1.如果让你设计一个 HashMap 如何设计?


这个问题我觉得可以从 HashMap 的一些关键点入手,例如 hash 函数、如何处理冲突、如何扩容。

可以先说下你对 HashMap 的理解。

比如:HashMap 无非就是一个存储 <key,value> 格式的集合,使得通过 key 在 O(1) 的时间复杂下就能查找到 value。

基本原理就是将 key 经过 hash 函数进行散列得到散列值,然后通过散列值对数组取模得到对应的 index 。

所以 hash 函数很关键,不仅运算要快,还需要分布均匀,减少 hash 碰撞。

而因为输入值是无限的,而数组的大小是有限的所以肯定会有碰撞,因此可以采用拉链法来处理冲突。

为了避免恶意的 hash 攻击,当拉链超过一定长度之后可以转为红黑树结构。

当然超过一定的结点还是需要扩容的,不然碰撞就太严重了。

而普通的扩容会导致某次 put 延时较大,特别是 HashMap 存储的数据比较多的时候,所以可以考虑和 redis 那样搞两个 table 延迟移动,一次可以只移动一部分。

不过这样内存比较吃紧,所以也是看场景来 trade off 了。

还有,最好使用之前预估准数据大小,避免频繁的扩容。

基本上这样答下来差不多了,HashMap 几个关键要素都包含了,接下来就看面试官怎么问了。

可能会延伸到线程安全之类的问题,反正就照着 currentHashMap 的设计答。

其实有些题目看起来是问如何设计,实际上你就答你对这个东西是怎么理解的,把它原理和一些要点讲一讲这个题目就过了。

比如我上面说的预估准数据的大小,这种看起来和设计没关系,但是可以让面试官知道你对这种方面是敏感的就够了。

所以有时候的“答非所问”是 OK 的,如果面试官觉得你答的方向不对,自然而然会提醒你,到时候你再接招就好了。

简单地说,很多提问不是真的要死板的对着面试题而回答,因为面试官也只是笼统地问


2.如果让你设计一个线程池如何设计?


这种设计类问题还是一样,先说下理解,表明你是知道这个东西的用处和原理的,然后开始 BB。基本上就是按照现有的设计来说,再添加一些个人见解。

线程池讲白了就是存储线程的一个容器,池内保存之前建立过的线程来重复执行任务,减少创建和销毁线程的开销,提高任务的响应速度,并便于线程的管理。

我个人觉得如果要设计一个线程池的话得考虑池内工作线程的管理、任务编排执行、线程池超负荷处理方案、监控等方面。

要将初始化线程数、核心线程数、最大线程池都暴露出来可配置,包括超过核心线程数的线程空闲消亡相关配置。

然后任务的存储结构也得可配置,可以是无界队列也可以是有界队列,也可以根据配置,分多个队列来分配不同优先级的任务,也可以采用 stealing 的机制来提高线程的利用率。

再提供配置来表明此线程池是 IO 密集型还是 CPU 密集型来改变任务的执行策略。

超负荷的方案可以有多种,包括丢弃任务、拒绝任务并抛出异常、丢弃最旧的任务或自定义等等。

至于监控的话,线程池设计要埋好点,暴露出用于监控的接口,如已处理任务数、待处理任务数、正在运行的线程数、拒绝的任务数等等信息。

我觉得基本上这样答就差不多了,等着面试官的追问就好。

注意不需要跟面试官解释什么叫核心线程数之类的,都懂的没必要。

当然这种开放型问题还是仁者见仁智者见智,我这个不是标准答案,仅供参考。

建议把线程池相关的关键字都要说出来,表面你对线程池的内部原理的理解是透彻的。


最后


近期应该有很多人在准备面试了,跳槽 time is up。

我也在加紧写面试题解,今天暂时就拿出这两个设计类题目来看看反响。

如果有什么建议留言哈。


相关文章
|
8天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
12天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
53 4
|
2月前
|
安全 Java 应用服务中间件
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
什么是类加载器,类加载器有哪些;什么是双亲委派模型,JVM为什么采用双亲委派机制,打破双亲委派机制;类装载的执行过程
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
|
1月前
lua面向对象(类)和lua协同线程与协同函数、Lua文件I/O
Lua的面向对象编程、协同线程与协同函数的概念和使用,以及Lua文件I/O操作的基本方法。
28 4
lua面向对象(类)和lua协同线程与协同函数、Lua文件I/O
|
24天前
|
存储 Java 程序员
Java面试加分点!一文读懂HashMap底层实现与扩容机制
本文详细解析了Java中经典的HashMap数据结构,包括其底层实现、扩容机制、put和查找过程、哈希函数以及JDK 1.7与1.8的差异。通过数组、链表和红黑树的组合,HashMap实现了高效的键值对存储与检索。文章还介绍了HashMap在不同版本中的优化,帮助读者更好地理解和应用这一重要工具。
52 5
|
24天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
19 3
|
24天前
|
Java
在Java多线程编程中,实现Runnable接口通常优于继承Thread类
【10月更文挑战第20天】在Java多线程编程中,实现Runnable接口通常优于继承Thread类。原因包括:1) Java只支持单继承,实现接口不受此限制;2) Runnable接口便于代码复用和线程池管理;3) 分离任务与线程,提高灵活性。因此,实现Runnable接口是更佳选择。
33 2
|
24天前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
28 2
|
25天前
|
存储 Java API
详细解析HashMap、TreeMap、LinkedHashMap等实现类,帮助您更好地理解和应用Java Map。
【10月更文挑战第19天】深入剖析Java Map:不仅是高效存储键值对的数据结构,更是展现设计艺术的典范。本文从基本概念、设计艺术和使用技巧三个方面,详细解析HashMap、TreeMap、LinkedHashMap等实现类,帮助您更好地理解和应用Java Map。
41 3
|
24天前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
28 1