首先,我常年混迹于各种各样的技术交流群,然后经常会有群友提供一些面试的题目,甚至考卷什么的,前几天一个正在找工作的技术比较N的小伙伴口述了他笔试的几道印象深刻的题,结果不出意外的我也一脸懵逼。
既然不会得学啊,结果一查才发现人家面试问的都是最基础的知识!对的,入门的基础,也是数学的基础。非科班出身的我反正有那么一丢丢印象不过用是不会用的,不知道科班出身会不会好一点。
不卖关子了,咱们直接说题目:
第一题
因为这个仁兄说没拍照,所以按照记忆会议几个题算几个。。
乍一看这个题我也很懵,甚至都怀疑是不是我学了个假java,完全没见过这种写法啊!但是代码最好的一点就是实践性强,随便找了各类,放上这个输出语句,输出结果7。
然后我心里暗暗怀疑,难不成这个|就是一个加的功能?不能吧,我开始百度
按位或
按位或
一看这个名字略耳熟啊,我好像学过?赶紧继续回忆,哦,对,这个是二进制的数学运算,按位或是位运算的一种,是将两个数据的二进制表示右对齐后,按位进行运算,两个对应的二进制位中只要一个是1,结果对应位就是1。
1 | 1 = 1 ,
1 | 0 = 1 ,
0 | 1 = 1 ,
0 | 0 = 0
所以3在二进制是11,
4在二进制是100。右对齐后运算,就是111。也就是十进制下的7。
这个确实是基础学的知识,但是真的有点冷门,反正我开发以来是没用过。所以忘得差不多了,这次算是重新复习基础了。
位移
哎呦呦,这个看明白了一半,恰好我这段时间在看hashMap的源码,所以>>>2这个操作还是勉强看懂了的,相当于原数除2再除2。如果除2结果是小数自动向小取整。(暂定这个数是正数的前提下)
比如题中31/2,结果是15.5,自动取15,因为在右移时不管最后一位是1还是0都舍去。
15/2结果是7.5,自动取7。
这一步确定了X为7。
按位异或
而I^ i^ X,这有涉及一个基础运算:按位异或,按位异或是位运算的一种,是将两个数据的二进制表示右对齐后,按位进行运算,两个对应的二进制位中数据不同,结果对应位就是1。
1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0
上文中,i^ i因为是两个相同数字比较,所以肯定每一位都相同,都为0,也就是结果是0,0^ x,X中为0的位还是0,为1的位还是1,所以结果还是x不变,也就是i^ i^x结果就是x,也就是7。
String的不可变性
这个题其实比较基础,所以这个我是会的,结果是1。因为String在java中的特殊,其本身就是final的,不可变的对象(不要用反射抬杠),所以像是replace,split等,都是生成新对象的。并不是改变原有对象。所以X(e)之后这个对象并没有改变,还是“1”。
String源码
好吧的,出于面试的大佬记忆问题,印象深刻的就这么几个,剩下都是面试的提问了,大佬也简单列了出来,我这里也截个图,因为这种开放性题目没有什么正经答案,所以我也是根据理解和查资料后写出来的,不准确见谅。有兴趣的小伙伴也可以自己查查资料背背书。
面试提问- 线程池的核心参数:
public ThreadPoolExecutor(
int corePoolSize, //核心池的大小。
int maximumPoolSize, //池中允许的最大线程数,这个参数表示了线程池中最多能创建的线程数量
long keepAliveTime, //当线程数大于corePoolSize时,终止前多余的空闲线程等待新任务的最长时间
TimeUnit unit, //keepAliveTime时间单位
BlockingQueue<Runnable> workQueue, //存储还没来得及执行的任务
ThreadFactory threadFactory, //执行程序创建新线程时使用的工厂
RejectedExecutionHandler handler //由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序
)
- 池中线程数小于corePoolSize,新任务都不排队而是直接添加新线程
- 池中线程数大于等于corePoolSize,workQueue未满,首选将新任务加入workQueue而不是添加新线程
- 池中线程数大于等于corePoolSize,workQueue已满,但是线程数小于maximumPoolSize,添加新的线程来处理被添加的任务
- 池中线程数大于大于corePoolSize,workQueue已满,并且线程数大于等于maximumPoolSize,新任务被拒绝,使用handler处理被拒绝的任务
- 为什么要先执行核心线程,任务来了放队列,队列满了才开启新线程(这个是开放试题,我找了很多资料,也没有正解,所以根据自己的理解来写的)
这个题首先涉及到创建一个新线程的性能消耗。
-
创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处理效率。
例如创建线程用T1时间,销毁用T2时间,结果执行任务用T3时间。如果T1+T2>T3,那么开启一个线程来执行这个任务太不划算了。所以同理,如果核心线程池满了,但是就来了一个任务,就为了这个任务开启一个线程,结果还没等开启完呢别的线程空出来甚至把这个任务都执行了,那不是扯呢么? -
线程并发数量过多,抢占系统资源从而导致阻塞
我感觉上面的是百分之八九十的原因,最后这个一个常识,线程并发数量越多,越容易出现阻塞问题。所以我们尽可能的控制线程数量合理,够用即可,不要冗余。
我用我惯用 的关联法来比喻:一家外包公司接了个项目,工期有点紧,现有员工做可能要加点班,你觉得公司会因为这样特意在顾员工做么?肯定是让现有员工加快工作效率,甚至偶尔加班啊。(不开新线程,任务来了放队列)
继续比喻:一家外包公司接了个项目,工期有点紧,现有员工做可能要不休周末才能做完,你觉得公司会因为这样特意在顾员工做么?也不会啊,最多周末加班被,给点补助就不错了的。(不开新线程,任务来了继续放队列)
但是!!如果现有员工加班加点,死在岗位上也做不完,那么迫于无奈,只能是招新员工了!(队列满了,只能开新线程了!)
好了,这次的总结就到这,主要是面试的兄弟就提供这么几道题。
全文手打不易,如果稍微帮到你了,请点个喜欢点个关注支持一下~~~~~也祝大家工作顺顺利利!
网友评论