【奇安信】-Java岗-服务端开发一二面面经
一面
一开始网不太好
1、学习java的方式
面试官说他那里加载不出来我简历,先随便问了一下。
2、说一下HashMap
允许put空值,如果key为null,那么hash值为0.
底层数据结构:数组 + 链表 + 红黑树
loadFactor:负载因子默认为0.75,是均衡了时间和空间损耗计算出来的,较高的值会减少空间的开销,扩容减小,数组大小增加速度变慢,但是增加了查找的成本,hash冲突增加,链表变长
如果有很多需要储存到HashMap中的数据,要在一开始把它的容量设置为足够大,防止出现不断扩容
线程不安全
重要的字段
DEFAULT_INITIAL_CAPICITY = 1 << 4; 默认大小为16 MAXIMUM_CAPACITY = 1 << 30; 最大容量 DEFAULT_LOAD_FACTOR = 0.75f; 默认负载因子 TREEIFY_THRESHOLD = 8; UNTREEIFY_THRESHOLD = 6; 树化和退化为链表的阈值 MIN_TREEIFY_CAPACITY = 64; 链表转化为红黑树时需要的数组大小 threshold 表示扩容的阈值,大小为 数组大小*负载因子
3、ConcurrentHashMap怎么保证线程安全?
底层基于CAS + synchronized实现,所有操作都是线程安全的,允许多个线程同时进行put、remove等操作
在JDK1.7采用的是Segment分段锁,默认并发度为16
改变的原因:竞争同一个锁的概率低,浪费内存空间,容易造成长时间等待,1.8对synchronized做了很多的优化。
table数组被volatile修饰
如果再问的细一点,就是put方法了,没值CAS添加,有值synchronized加锁。
4、Synchronized做过哪些优化?
参考《深入理解JAVA虚拟机》从无锁状态到偏向锁再到轻量级锁,再到重量级锁的一个升级,自适应自旋等等这些。
5、类加载的过程?
加载—链接(验证、准备、解析)—-初始化
加载:生成一个代表类的Class对象,作为方法区中该类各种数据的访问入口。
验证:确保包含的信息符号当前虚拟机的要求,不会危害虚拟机自身的安全。
准备:为类变量分配内存,设置初始值
解析:将常量池的符号引用替换为直接引用的过程。
初始化:执行Java程序代码。
6、MySQL索引数据结构详细说一下
B+树
从二叉查找树到二叉平衡树再到B树再到B+树,分别说每个是否适合做索引,以及不同数据结构的区别
7、具体说一下查询的过程(聚集索引、非聚集索引、联合索引)
这里说了一下聚集索引查找和非聚集索引查找的过程
聚集索引:索引即数据
非聚集索引要回表查询。
联合索引:最左匹配原则:最左优先,以最左边为起点任何连续的索引都能匹配上。同时遇到范围查询就会停止匹配。
= in 可以乱序
(a,b,c) 可以用到索引的情况(a,b (a,c) (b,a) (c,a) 三个一起的都可以用到,不管顺序如何
8、MySQL的架构,分几层?
9、Innodb事务?
ACID老八股了
10、介绍下MCVV
多版本并发控制,新增两个字段,最后一次修改的事务ID,指向回滚的undolog指针
这里我有个疑问,到底RR解决幻读了吗?网上文章很多,说什么的都有。
11、计算机网络7层架构
物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
12、 HTTPS协议?详细介绍
简洁的说,就是有公钥和密钥,加密用公钥解密用密钥,这是非对称加密。
HTTPS为了兼顾安全与效率,同时使用了对称加密和非对称加密。数据是被对称加密传输的,对称加密过程需要客户端的一个密钥,为了确保能把该密钥安全传输到服务器端,采用非对称加密对该密钥进行加密传输,总的来说,对数据进行对称加密,对称加密所要使用的密钥通过非对称加密传输。
答完这个,面试官说没问题,很棒😂,感觉问的都还挺简单的,都是八股。而且全部按照简历上写的来问。
13、SpringBoot的自动装配原理?
@EnableAutoConfiguration 注解,深入进去说一下springboot怎么扫描怎么装配就行了。
14、Redis持久化机制
rdb
aof
15、Redis主从复制
一般面试都没问过这个,因为这次全是按照简历里面写的问,我简历里面写了,但还是第一次被问到,好久没复习了。
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器,前者称为主节点(master/leader),后者称为从节点(slave/follower)Master以写为主,Slave以读为主。
16、哨兵机制
哨兵是一个独立的进程,作为进程,它会独立运行,其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行多个Redis实例。
17、对分布式的理解?
将大的项目拆分成不同的模块,部署到不同的机器上,就是把单体架构拆分成不同的微服务,
分布式系统的优点:
提升服务可用性 / 稳定性
提升系统并发能力
提升系统容错能力
低延迟
分布式系统缺点:
依赖网络,会因为网络问题导致系统数据丢失或不一致性;
系统复杂化,系统监控维护,版本迭代发布变得相对复杂,成本高;
一致性,可用性,分区容错性无法同时满足。
二面
1、自我介绍
2、项目讨论
一般面试环节,提到项目上的问题,我很乐意和面试官去讨论项目上的一些实现,如果面试官也去深入分析项目上的细节,去分析项目可以优化的点,我感觉面试体验是很好的,因为这样不仅能让自己对项目更加熟悉,也可以知道自己有哪些不足,这是很重要的。但是如果提到项目,面试官脱离项目,直接问一些使用的技术上的问题,那我感觉就会比较不太好回答。
3、Java封装、继承、多态、谈谈你对封装的理解?
将一个对象的属性私有化,行为公开化,同时提供对外的接口来访问对象,数据被保护在抽象数据类型的内部,尽可能的隐藏内部的细节,只保留一些对外的接口使其与外部发生联系。用户无需关心对象内部的细节。优点是减少了耦合。
4、Java集合
ArrayList和LinkedList
分别从底层数据结构和使用场景上分析
ArrayList底层是数组,适合快速的匹配,不适合频繁的增删
LinkedList底层是链表,适合增删,不适合频繁的匹配,一般用它可以实现栈或者队列
5、创建线程的几种方式
1、继承Thread类,
2、实现Runnable接口;
3、实现Callable接口;可以有返回值,返回值通过FutureTask进行封装。
4、线程池实现
6、线程池参数+(拒绝策略)
1、corePoolSize:线程池核心线程大小。
2、maximumPoolSize:线程池最大线程数量。
3、keepAliveTime:空闲线程存活时间。
4、unit:空闲线程存活时间单位。
5、workQueue:工作队列
6、threadFactory 线程工厂 (指定优先级,指定线程名称,方便监控,指定是否是守护线程)
7、handler 拒绝策略
1、CallerRunsPolicy:哪来的去哪里
2、AbortPolicy:直接丢弃任务,并抛出RejectedExecutionException异常。
3、DiscardPolicy:直接丢弃任务,什么都不做。
4、DiscardOlddestPolicy:抛弃进入队列最早的那个任务,然后尝试把这次拒绝的任务放入队列。(LRU)
7、核心线程数和最大线程数平时使用的时候怎么设置?
这里我答了一下线程池的执行流程,然后分析了CPU密集型和IO密集型的线程数设置。
CPU密集 :N+1
IO密集:2N+1
最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目
这里面试官说了,一些资料或者博客上面都是这样整理的,实际上在真实的开发中,CPU密集型也有,IO密集型也有,往往是混合使用的,真正怎么设置,还要实际去操作过才可以。
(这种讨论式的面试,体验很好,八股都会背,但是面试官可能会跟你延申一下其他的,面试过程中,自己也能学到不少思想和知识。)
8、异步编排,好几个线程协同的完成任务
这个问题出现概率很高,其实就是变相的问,线程之间同步。可以参考生产者消费者来延申回答。
9、Synchronized和Lock区别
直接每个锁深入底层和面试官讨论,这样能加很多分。
1、Synchronized 是内置的Java关键字,Lock是一个Java类。
2、Synchronized 无法判断获取锁的状态,Lock可以判断是否获取到了锁。
3、Synchronized 会自动释放锁,Lock必须要手动释放锁,如果不释放锁会造成死锁。
4、Synchronized 线程1(获得锁,阻塞)线程2(等待,傻傻的等)Lock锁不会一直等待下去。
5、Synchronized 可重入锁,不可中断,非公平,Lock可重入锁,可以中断锁,可以自己设置非公平。
6、Synchronized 适合锁少量代码同步问题,Lock 适合锁大量的同步代码!
10、公平锁和非公平锁的效率那种效率更高?
在我印象中,肯定是非公平锁的效率更高啊,因为它是采用了cas去争夺锁的,公平的话,是直接放在队列尾部的。
然后面试官说,其实实际的话,如果非公平竞争也是有开销的,公平的话,就去队列中取出其中的一个。具体情况还要具体分析。
11、刚刚你有谈到对象有个MarkWord,java对象在内存中的组成部分?
从new开始讲起来
1、类加载
2、分配内存
3、初始化
4、设置对象头
5、执行init方法
12、Java反射Class对象,存在那个区域?
堆中,堆中都是放对象的。
13、方法区放什么东西?
存储已被虚拟机加载的类型的信息,常量,静态变量,即时编译器编译后的代码缓存。会发生OutOfMemoryError.
14、Java是编译型语言还是解释型语言?
其实Java是混合型的
Java代码在执行时,先通过Javac编译为字节码,在运行时,通过JVM内的解释器转换为目标机器的可执行机器码。
但是常见JVM、比如Hotspot JVM都提供JIT(just in time) 动态编译器 ,能够在运行时将热点代码直接翻译成机器码,这部分属于编译执行
15、Java编译型语言,实现多态
继承和接口
编译时多态 指的是重载,运行时指的是对象引用所指向的具体类型在运行期间才确定。一个变量到底指向哪个实例类,该引用变量发出的方法调用是由哪个类实现的,必须程序运行时才能确定,
16、InnoDB主键索引的数据结构?
B+树
17、B+树相对B树的优势?
更矮更胖
18、UUID B+树的效率
肯定不会高,因为索引是占内存空间的,键越多,效率就越低,而且uuid排序不太友好。
19、UUID B+树的效率不高,那我们可以选取那种数据结构呢?
这里我一开始想到Trie树,uuid,trie树,面试官说也是一种方法。
后面说了hash,但是我想hash的话,没办法范围查找,范围查找是问题,不过面试官就是想要这个答案,然后引申出,java的hashmap,我恍然大悟,哈哈哈。
hash来建索引的话,是不错的选择,但是前提是没有范围查找。
20、最左匹配原则
如果a范围,后面还会用到索引吗?
肯定不会,最左匹配遇到范围就会终止的。
Like查询呢?
like xx%会走索引
like %xx不会走索引
反问