大小厂必问 Java 后端面试题(含答案)

面霸系列之 Java 基础篇第一版肝出来了,说实话每个问题其实都能展开来写一篇文章....

这个系列的文章不会是背诵版,不是那种贴上标准答案,到时候照着答就行的面试题汇总。

我会用大白话尽量用解释性、理解性的语言来回答,但是肯定没有比平时通过一篇文章来讲解清晰,不过我尽量。

暂时我先放 20 题出来,字数实在太多了,放一些之后看反馈,然后再修订,之后再搞个 pdf。

还有,虽说看着只有 20 题,其实不止,因为有些题目我没拆解,回答中会有延伸问题,所以题目数不止我列出的这些,内容还是非常多的。

剩下还有几十题,先亮一亮题目,嘿嘿。

1.你觉得 Java 好在哪儿?

这种笼统的问题如果对某些知识点没有深入、系统地认识绝对会蒙!

所以为什么经常碰到面试官问你一些空、大的问题?其实就是考察你是否有形成体系的理解。

回到问题本身。我觉得可以从跨平台、垃圾回收、生态三个方面来阐述。

首先 Java 是跨平台的,不同平台执行的机器码是不一样的,而 Java 因为加了一层中间层 JVM ,所以可以做到一次编写多平台运行,即 「Write once,Run anywhere」。

编译执行过程是先把 Java 源代码编译成字节码,字节码再由 JVM 解释或 JIT 编译执行,而因为 JIT 编译时需要预热的,所以还提供了 AOT(Ahead-of-Time Compilation),可以直接把字节码转成机器码,来让程序重启之后能迅速拉满战斗力。

(解释执行比编译执行效率差,你想想每次给你英语让你翻译阅读,还是直接给你看中文,哪个快?)

Java 还提供垃圾自动回收功能,虽说手动管理内存意味着自由、精细化地掌控,但是很容易出错。

在内存较充裕的当下,将内存的管理交给 GC 来做,减轻了程序员编程的负担,提升了开发效率,更加划算!

然后现在 Java 生态圈太全了,丰富的第三方类库、网上全面的资料、企业级框架、各种中间件等等,总之你要的都有。

基本上这样答差不多了,之后等着面试官延伸。

当然这种开放性问题没有固定答案,我的回答仅供参考。

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

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

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

比如:HashMap 无非就是一个存储 <key,value> 格式的集合,用于通过 key 就能快速查找到 value。

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

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

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

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

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

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

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

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

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

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

3.并发类库提供的线程池实现有哪些?

虽说阿里巴巴 Java 开发手册禁止使用这些实现来创建线程池,但是这问题我被问过好几次,也是热点。

问着问着就会延伸到线程池是怎么设计的。

我先来说下线程池的内部逻辑,这样才能理解这几个实现。

首先线程池有几个关键的配置:核心线程数、最大线程数、空闲存活时间、工作队列、拒绝策略。

  1. 默认情况下线程不会预创建,所以是来任务之后才会创建线程(设置 prestartAllCoreThreads 可以预创建核心线程)。

  2. 当核心线程满了之后不会新建线程,而是把任务堆积到工作队列中。

  3. 如果工作队列放不下了,然后才会新增线程,直至达到最大线程数。

  4. 如果工作队列满了,然后也已经达到最大线程数了,这时候来任务会执行拒绝策略。

  5. 如果线程空闲时间超过空闲存活时间,并且线程线程数是大于核心线程数的则会销毁线程,直到线程数等于核心线程数(设置 allowCoreThreadTimeOut 可以回收核心线程)。

我们再回到面试题来,这个实现指的就是 Executors 的 5 个静态工厂方法:

  • newFixedThreadPool

  • newWorkStealingPool

  • newSingleThreadExecutor

  • newCachedThreadPool

  • newScheduledThreadPool

newFixedThreadPool

这个线程池实现特点是核心线程数和最大线程数是一致的,然后 keepAliveTime 的时间是 0 ,队列是无界队列。

按照这几个设定可以得知它任务线程数是固定,如其名 Fixed。

然后可能出现 OOM 的现象,因为队列是无界的,所以任务可能挤爆内存。

它的特性就是我就固定出这么多线程,多余的任务就排队,就算队伍排爆了我也不管

因此不建议用这个方式来创建线程池。

newWorkStealingPool

这个是 1.8 才有的,从代码可以看到返回的就是 ForkJoinPool,我们 1.8 用的并行流就是这个线程池。

比如users.parallelStream().filter(...).sum();用的就是 ForkJoinPool 。

从图中可以看到线程数会参照当前服务器可用的处理核心数,我记得并行数是核心数-1。

这个线程池的特性从名字就可以看出 Stealing,会窃取任务

每个线程都有自己的双端队列,当自己队列的任务处理完毕之后,会去别的线程的任务队列尾部拿任务来执行,加快任务的执行速率。

至于 ForkJoin 的话,就是分而治之,把大任务分解成一个个小任务,然后分配执行之后再总和结果,再详细就自行查阅资料啦~

newSingleThreadExecutor

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
几十个Java示例程序,搞懂了考试不成问题 【程序1】 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一 对兔子,假如兔子都不死,每个月的兔子总数为多少? 1.程序分析: 兔子的规律为数列1,1,2,3,5,8,13,21.... 【程序2】 题目:判断101-200之间有多少个素数,并输出所有素数。 1.程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除, 则表明此数不是素数,反之是素数。 【程序3】 题目:打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身。例如: 153是一个"水仙花数",因为153=1的三次方+5的三次方+3的三次方。 1.程序分析:利用for循环控制100-999个数,每个数分解出个位,十位,百位。 【程序4】 题目:将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5。 程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成: (1)如果这个质数恰等于n,则说明分解质因数的过程已经结束,打印出即可。 (2)如果nk,但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数你n,重复执行第一步。 (3)如果n不能被k整除,则用k+1作为k的值,重复执行第一步。 【程序5】 题目:利用条件运算符的嵌套来完成此题:学习成绩>=90分的同学用A表示,60-89分之间的用B表示,60分以下 的用C表示。 1.程序分析:(a>b)?a:b这是条件运算符的基本例子。 【程序6】 题目:输入两个正整数m和n,求其最大公约数和最小公倍数。 1.程序分析:利用辗除法。 【程序7】 题目:输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。 1.程序分析:利用while语句,条件为输入的字符不为'\n'. 【程序8】 题目:求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字。例如2+22+222+2222+22222(此时共有5个数相加), 几个数相加有键盘控制。 1.程序分析:关键是计算出每一项的值。 【程序9】 题目:一个数如果恰好等于它的因子之和,这个数就称为"完数"。例如6=1+2+3.编程 找出1000以内的所有完 数。 【程序10】 题目:一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在 第10次落地时,共经过多 少米?第10次反弹多高? 【程序11】 题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 1.程序分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去 掉不满足条件的排列。 【程序12】 题目:企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万 元时,低于10万元的部分按10%提成,高于10万元的部分,可可提成7.5%;20万到40万之间时,高于20万元的部 分,可提成5%;40万到60万之间时高于40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可 提成1.5%,高于100万元时,超过100万元的部分按1%提成,从键盘输入当月利润I,求应发放奖金总数? 1.程序分析:请利用数轴来分界,定位。注意定义时需把奖金定义成长整型。 【程序13】 题目:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请该数是多少? 1.程序分析:在10万以内判断,先将该数加上100后再开方,再将该数加上268后再开方,如果开方后的结果满足 如下条件,即是结果。请看具体分析: 【程序14】 题目:输入某年某月某日,判断这一天是这一年的第几天? 1.程序分析:以3月5日为例,应该先把前两个月的加起来,然后再加上5天即本年的第几天,特殊情况,闰年且 输入月份大于3时需考虑多加一天。 【程序15】 题目:输入三个整数x,y,z,请把这三个数由小到大输出。 1.程序分析:我们想办法把最小的数放到x上,先将x与y进行比较,如果x>y则将x与y的值进行交换,然后再用x 与z进行比较,如果x>z则将x与z的值进行交换,这样能使x最小。 【程序16】 题目:输出9*9口诀。 1.程序分析:分行与列考虑,共9行9列,i控制行,j控制列。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值