虾皮java后端一面面经(刷水友面经)

作者:牛客122897821号
链接:https://www.nowcoder.com/discuss/682340?source_id=discuss_experience_nctrack&channel=-1
来源:牛客网

0、自我介绍
1、面向对象的特性

Java是一个面向对象的语言,不同于c或者c++是面向过程的语言,面向对象有三大特性,继承、封装和多态。
继承是子类继承了父类的属性和方法,私有属性子类是继承拥有的,只不过子类并不能访问父类的私有属性,子类可以对父类的属性覆盖,对方法进行重写。
封装就类似与U盘的使用,所有的内部逻辑是不需要我们知道的,唯一给我们使用的就是方法的接口,传入参数来使用封装的东西。
多态分为编译时多态和运行时多态,编译时多态就是重载,方法名字相同,但参数的类型,顺序和数量不同,程序在编译时就可以确定要执行哪个方法。
而运行时多态就是重写,重写方法的参数类型顺序都是相同的,一般用@override来标识,因为程序在编译时并不能确定要执行哪个方法,只有在程序运行起来的时候才能根据应用对象来确定执行哪个方法。

2、JVM内存划分

JVM内存划分有方法区,堆区,本地方法栈和Java栈和一个PC计数器
PC计数器是私有的用来记录程序执行到了哪一行
栈的作用是用来存放局部变量,操作数栈等
本地方法栈存放的是底层的一些方法
堆和方法区我觉得是最重要的两个模块,方法区内存放的有是static整个程序中唯一存在的元素和常量池
堆是为对象开辟空间内存的地方,分为年轻代和老年代,年轻代又分为伊甸园区和幸存者0,1区且年轻代和老年代的比例是1:2,伊甸园区和幸存者区的比例是8:1

3、线程池的构造参数

线程池的构造参数又corePoolSize核心线程数,maximumsize最大支持的核心线程数,keepAliveTime等待时间,unit时间单位,blockingQueue阻塞队列,默认工厂和handler拒绝策略
corePoolSize核心线程数是该线程池要保留的线程数目即使这些线程是空闲的
maximum是线程池中允许的最大线程数,如果线程超过了corePoolSize那么这些多出来的线程将会被销毁最终剩余corePoolSize个线程。
keepAliveTime是多出corePoolSize的线程等待任务的时间,如果等待时间超过了keepAliveTime那么这些线程就会被销毁。
unit是设置keepAliveTime的等待时间的单位
blockingQueue是阻塞队列,有ArrayBlockingQueue基于数组的有界队列,LinkedBlockingQueue基于链表的无界队列也可以自己定义队列中等待线程的数量,synchronionBolckingQueue是不存储元素的队列,必须等待有线程移除才会执行线程的插入,否则会一直阻塞。PriorityBlockingQueue支持优先级的阻塞队列
默认工厂是创建新线程时使用的工厂,一般就是默认的
handler是拒绝策略,有四种拒绝策略,拒绝任务并抛出异常,拒绝任务不抛出异常,丢弃最早的任务来执行最新的任务和拒绝任务由调用该任务的线程执行该任务,例如该拒绝策略下main线程也可以执行任务。

4、向线程池添加任务后线程池的处理逻辑

向线程池提交任务后,线程池会首先判断任务数量是否已经达到了corePoolSize,如果任务数量没有达到corePoolSize那么该任务就会创建一个新线程来执行这个任务,如果核心线程池已经满了,那么新的任务就会被加入到阻塞队列中,如果阻塞队列已经满了并且线程数目没有达到maximumPoolSize那么就会创建新的线程来执行任务,如果阻塞队列和maximumPoolSize都满了那么新来的任务就会被拒绝策略拒绝,线程池默认的拒绝策略就是拒绝并抛出异常。

5、GC垃圾收集器

垃圾收集器有并行垃圾收集器和穿行的垃圾收集器,最主要的垃圾收集器是CMS与G1收集器,CMS垃圾回收期是current-mark-swap,初始标记-并发标记-重新标记-并发清理
第一阶段为初始标记,为标记垃圾此阶段会触发STW将所有的线程停止来标记垃圾
第二阶段为并发标记,为初始标记完成后所有的线程会重新运行,并发标记并不会触发STW,而是和运行的线程一起运行的
第三阶段为重新标记,重新标记的主要作用就是重新确定第二阶段的并发标记标记的垃圾是否随着用户线程的运行而gai'bian
第四阶段为并发清理,清理标记的垃圾。
CMS的缺点就是无法处理第三阶段产生的垃圾,因为第三阶段只是对第二阶段的垃圾的确认,而并没有去重新的标记垃圾。

G1垃圾回收器顾名思义就是Garbage first就是垃圾第一,G1会把整个堆区分割成物理空间上不连续的空间,使用不同的块来表示幸存者区,伊甸园区,老年代和一个humongous区,G1就判断每个区的垃圾的回收价值,根据每次回收的时间来判断哪个区域回收垃圾多而且腾出的区域大。至于为什么要设置Region第一就是回收的时候可以根据回收价值来回收垃圾,效率较高,第二个原因就是如果是生命周期较短的大对象默认被分配到老年代而通常的垃圾回收器老年代都是回收频率不高的,那么这样就会导致内存空间上的浪费,而G1收集器就是直接会判断到这个老年代的块垃圾回收价值,高的话就会直接将这个生命周期短的大对象回收掉。
G1收集器的垃圾回收机制就是当伊甸园区用完的时候就会对年轻代进行回收,当达到老年代区域的阈值的时候就会回收老年代。

6、垃圾收集算法,为什么新生代用标记-复制老年代用标记-整理

新生代的区域分为伊甸园区,幸存者0和幸存者1区,具体的标记复制算法过程是:当Eden区满了之后就会触发YGC,第一次是将Eden区回收后存活的对象放到幸存者0区,当Eden区再次满的时候,会同时回收Eden区和幸存者0区,将存活的对象放到幸存者1区,当存活对象经过了15轮还存活时,该对象就会进入老年代。垃圾回收就是用的复制算法,将Eden区和幸存者0区存活的对象复制到幸存者1区,然后对Eden区和幸存者0区全部清理。老年代中的对象都是存活时间比较长的对象,所以用标记整理比较好,标记整理就是将标记的存活对象整理到内存的一端,回收剩下的。

7、数据库索引,索引怎么优化


8、联合索引(a,b)直接查b会用到索引a吗

不会,因为索引的使用必须要符合最左匹配原则,直接走b并不会用到索引a

9、TCP和UDP区别

10、打开一个网址的过程,用到的协议

11、程序CPU占用特别高,怎么排查问题
12、进程上下文切换指什么?保存现场保存哪些信息
13、上下文切换会发生在哪些时间?
14、编程:根据前序遍历和中序遍历构造二叉树
15、反问
#面经##Shopee##校招##Java工程师#
全部评论
可以的老哥😍
点赞 回复 分享
发布于 2021-07-22 21:41
强啊…
点赞 回复 分享
发布于 2021-07-23 11:45
老哥很nb,比我当时答的详细的多,补充一下CMS的缺点:一是因为concurrent导致的cpu资源要求比较高,二是你说到的这个浮动垃圾的问题,三是标记清除法带来的内存碎片的问题(这个我觉得最严重,我也没搞懂为啥要设计成标记清除,独此一家好吧)。
点赞 回复 分享
发布于 2021-07-23 22:18
这是SP 还是SSP面试啊
点赞 回复 分享
发布于 2021-07-30 16:33

相关推荐

6 63 评论
分享
牛客网
牛客企业服务