ConcurrentHashMap 在扩容时会计算出一个步长(stride),最小值是16,然后给当前扩容线程分配“一个步长”的节点数,例如16个,让该线程去对这16个节点进行扩容操作(将节点从老表移动到新表)。
如果在扩容结束前又来一个线程,则也会给该线程分配一个步长的节点数让该线程去扩容。依次类推,以达到多线程并发扩容的效果。
AQS中有多个线程并发添加到队列中,需要做并发控制吗
这个是需要的,源码中是通过 CAS 来进行并发控制。
在 addWaiter(Node mode) 方法中,如果并发添加节点,则只会有一个线程成功,另一个会失败,从而走到 enq(node) 方法中去进行重试。
说实话,虽然看过源码,但是真的很难记得这么多细节,因为 Java 面试要准备的东西实在太多了,所以这边可以利用一个小技巧。
小技巧:首先并发控制肯定是要做的,这个不难推测;接着,如果注意观察的话,不难发现在 JDK 源码中做并发控制的方式大多是 CAS,所以当你不知道怎么做并发控制的时候,可以直接蒙个 CAS,很有可能就被你蒙对了。
线程池有多个线程同时没取到任务****,会全部回收吗****
这个题不是很好理解,举个例子:线程池核心线程数是5,当前工作线程数为6(6>5,意味着当前可以触发线程回收),如果此时有3个线程同时超时没有获取到任务,这3个线程会都被回收销毁吗。
也是非常刁钻的一题,非常细节。但是即使我们记不得源码的细节了,还是有办法去推敲出来的。
思路:这道题的核心点在于有多个线程同时超时获取不到任务。正常情况下,此时会触发线程回收的流程。
但是我们知道,正常不设置 allowCoreThreadTimeOut 变量时,线程池即使没有任务处理,也会保持核心线程数的线程。
如果这边3个线程被全部回收,那此时线程数就变成了3个,不符合核心线程数5个,所以这边我们可以首先得出答案:不会被全部回收。这个时候面试官肯定会问为什么?
根据答案不难推测,为了防止本题的这种并发回收问题的出现,线程回收的流程必然会有并发控制。
what?又是并发控制,那不是又可以用到上面刚讲的“小技巧”?没错,源码中确实又是使用 CAS 来进行并发控制,从而保证在本例中只会有一个线程成功被回收。
本例相关源码在:getT****ask() 方法中。
多个AOP的顺序怎么定
通过 Ordered 和 PriorityOrdered 接口进行排序。
思路:这个问题其实我也也没准备过,但是我知道在 Spring 中有专门定义了 Ordered 和 PriorityOrdered 接口来实现排序功能,例如:对 BeanFactoryPostProcessor 的排序就是使用的这两个接口,所以这边我是直接猜测的用的这两个接口,结果还真是,所以说平时多积累还是挺重要的。
Object的wait()方法为什么需要先获取锁
这个问题说难也难,说简单也简单。
说简单是因为,大家应该都记得有道题目:“sleep和wait的区别”,答案中有一项就是:“wait会释放对象锁,sleep不会”,既然要释放锁,那必然要先获取锁。
说难是因为如果没有联想到这个题目并且没有了解 wait() 的底层原理,可能就完全没头绪了。
在 JVM 源码中,wait() 的底层逻辑会释放当前占有的锁,在释放前会进行锁的检查,如果当前线程没有持有锁,则会直接抛出 IllegalMonitorStateException。
synchronize底层维护了几个列表存放被阻塞的线程
这题是紧接着上一题的,很明显面试官想看看我是不是真的对 synchronize 底层原理有所了解。
synchronize 底层使用了3个双向链表来存放被阻塞的线程,3个双向链表分别是:_cxq(Contention queue)、_EntryList(EntryList)、_WaitSet(WaitSet)。
当线程获取锁失败进入阻塞后,首先会被加入到 _cxq 链表,_cxq 链表的节点会被进一步转移到 _EntryList 链表。
当持有锁的线程释放锁后,_EntryList 链表头结点的线程会被唤醒,该线程称为 OnDeck 线程,然后该线程会尝试抢占锁。
而当我们调用 wait() 时,线程会被放入 _WaitSet,直到调用了 notify()/notifyAll() 后,线程才被重新放入 _cxq 或 _EntryList,默认放入 _cxq 链表头部。
****真题:算法题、手写代码
===================
****单链表反转、****合并两个有序链表、********版本号比较
送分题,出这种题说明你前面面的不错,笔试题只是走个过场,力扣原题:21、165、206。
多线程按顺序输出ABC若干次
思路:考察多线程基础,Semaphore、Lock + Condition、synchronize 都有解法。
单例模式
手写单例模式,加上以前几次的面试,我有印象的至少有两个大厂问过了,还是挺重要的。通常有五种:懒汉、饿汉、双重检测、静态内部类、枚举,参考之前的文章:《单例模式详解》
手写阻塞队列
参考 ArrayBlockingQueue,实现 put 和 take 方法即可。
手写HashMap
JDK 1.8 的版本有点太复杂了,可以写 JDK 1.7 的版本,使用链表 + 数组实现,实现 get 和 put 方法即可。
输出一个二叉树的宽度
思路:二叉树的层序遍历(力扣102)的简单变形,记录下每层的节点个数,取最大值即可。
阿拉伯数字转汉字
例如:输入123.123,输出一百二十三点一二三。
思路:将“零一二三四五六七八九”、“十百千万亿”这些结果用到的字符存到数组,然后将阿拉伯数字转字符串,遍历拼接结果。
我当时的思路是将整数部分和小数部分分开处理,小数部分比较容易,主要是整数部分比较难处理,整数部分我当时第一想法是从低位往高位遍历,然后按每一位拼接,例如123,则拼出:三、二十、一百,最终组成:一百二十三。
这题思路不难想,方法应该有很多种,但是要能通过测试用例还是挺难的,很多细节需要处理,需要反复调试。
有序列表,找出所有两数之和为10000的组合
思路:可以用 HashMap 来存遍历过的数字,每次遍历时检查下 HashMap 里是否有目标数字,时间复杂度O(n),空间复杂度为O(n)。
如果面试官要求空间复杂度更优的解法,则可以用双指针,从列表的两边向中间扫,和小于10000,则左指针右移,和大于10000,则右指针左移,双指针理论上没有使用额外的空间。
单链表奇数节点移动到最前面
输入:a1->a2->a3->a4->a5
输出:a1->a3->a5->a2->a4
思路:也是硬写,不过这题还是有点规律的,只移动奇数节点,相当于移动一个,跳过一个,移动一个,跳过一个。
字符串的全排列
输入:s = “abc”
输出:[“abc”,“acb”,“bac”,“bca”,“cab”,“cba”]
思路:回溯法,按顺序固定每一位,同时排除同一位出现重复的情况,剑指 Offer 38 题。
最长上升子序列
输入: [10,9,2,5,3,7,101,18]
输出: 4 ,最长的上升子序列是 [2,3,7,101],它的长度是 4。
思路:动态规划,力扣 300 题。
****真题:项目、架构、管理
===================
项目介绍
必问的题目,项目介绍主要有两个重点:
1、要让面试官知道你在做什么。可以从项目的背景开始,为什么要做这个项目,按项目的演进过程、分阶段介绍。
2、突出项目的亮点和关键技术。面试官毕竟只是在听一个他没接触过的项目,所以他会更容易去抓取候选人介绍中的一些感兴趣的“关键词语”来提问,例如:从0到1、技术选型、性能优化、表达式引擎、规则引擎、平台化、技术重构、架构升级等等。
当然,你如果提到这些词,就要做好被追问的准备。
技术选型
技术选型主要比较几个维度:性能、稳定性、接入成本、社区活跃度、业务扩展性、业务特点等等,没有所谓最好的框架/工具,只有最合适自己的。
这边拿表达式引擎来作为例子:
我自己选用的是 Aviator,首先我会介绍 Aviator 的基本特点,然后跟 IKExpression、Groovy 进行对比,重点突出 Aviator 的优点:高性能、轻量级,并且强调 Aviator 已经足够满足业务需求,同时其作者在阿里方便进行交流等等。
做过最牛逼的功能
我经常看到有同学吐槽这个问题,但是这个问题说实话问的频率非常高,所以面试前还是得好好准备一下,争取能让面试官眼前一亮。此时不装逼,更待何时。
我这次讲的是一个性能优化的案例,将一个接口从性能提升了两个量级,不看过程只看结果还是有点吓人的。并且讲完案例后,我通常会继续分享一些自己在性能优化方面的研究和积累。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
总结
以上是字节二面的一些问题,面完之后其实挺后悔的,没有提前把各个知识点都复习到位。现在重新好好复习手上的面试大全资料(含JAVA、MySQL、算法、Redis、JVM、架构、中间件、RabbitMQ、设计模式、Spring等),现在起闭关修炼半个月,争取早日上岸!!!
下面给大家分享下我的面试大全资料
- 第一份是我的后端JAVA面试大全
后端JAVA面试大全
- 第二份是MySQL+Redis学习笔记+算法+JVM+JAVA核心知识整理
MySQL+Redis学习笔记算法+JVM+JAVA核心知识整理
- 第三份是Spring全家桶资料
MySQL+Redis学习笔记算法+JVM+JAVA核心知识整理
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
MySQL+Redis学习笔记算法+JVM+JAVA核心知识整理
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算