前言
今年,从java转到别的行业的人不少,也有不少人挤进这个市场想要分得一杯羹。年复一年,年年如此。当然,Java程序员市场需求依然是比较大的,而且Java岗位晋升方向多,这就为许多人带去了机会。但是另一方面,高级人才紧缺,很多即使是有工作经验的程序员都达不到大厂招聘的要求,对比一下蚂蚁,看下你离高级程序员还差几步?
蚂蚁一面
1、⼆叉搜索树和平衡⼆叉树有什么关系?
平衡⼆叉树也叫做平衡⼆叉搜索树,是⼆叉搜索树的升级版,⼆叉搜索树是指节点左边的所有节点都⽐该节点⼩,节点右边的节点都⽐该节点⼤,⽽平衡⼆叉搜索树是在⼆叉搜索的基础上还规定了节点左右两边的⼦树⾼度差的绝对值不能超过1
2、强平衡⼆叉树和弱平衡⼆叉树有什么区别
强平衡⼆叉树AVL树,弱平衡⼆叉树就是我们说的红⿊树。
-
AVL树⽐红⿊树对于平衡的程度更加严格,在相同节点的情况下,AVL树的⾼度低于红⿊树
-
红⿊树中增加了⼀个节点颜⾊的概念
-
AVL树的旋转操作⽐红⿊树的旋转操作更耗时
3、B树和B+树的区别,为什么Mysql使⽤B+树
B树的特点:
-
节点排序
-
⼀个节点了可以存多个元素,多个元素也排序了
B+树的特点:
-
拥有B树的特点
-
叶⼦节点之间有指针
-
⾮叶⼦节点上的元素在叶⼦节点上都冗余了,也就是叶⼦节点中存储了所有的元素,并且排好顺序
Mysql索引使⽤的是B+树,因为索引是⽤来加快查询的,⽽B+树通过对数据进⾏排序所以是可以提⾼查询速度的,然后通过⼀个节点中可以存储多个元素,从⽽可以使得B+树的⾼度不会太⾼,在Mysql中⼀个Innodb⻚就是⼀个B+树节点,⼀个Innodb⻚默认16kb,所以⼀般情况下⼀颗两层的B+树可以存2000万⾏左右的数据,然后通过利⽤B+树叶⼦节点存储了所有数据并且进⾏了排序,并且叶⼦节点之间有指针,可以很好的⽀持全表扫描,范围查找等SQL语句。
4、epoll和poll的区别
-
select模型,使⽤的是数组来存储Socket连接⽂件描述符,容量是固定的,需要通过轮询来判断是否发⽣了IO事件
-
poll模型,使⽤的是链表来存储Socket连接⽂件描述符,容量是不固定的,同样需要通过轮询来判断是否发⽣了IO事件
-
epoll模型,epoll和poll是完全不同的,epoll是⼀种事件通知模型,当发⽣了IO事件时,应⽤程序才进⾏IO操作,不需要像poll模型那样主动去轮询
5、简述线程池原理,FixedThreadPool⽤的阻塞队列是什么
线程池内部是通过队列+线程实现的,当我们利⽤线程池执⾏任务时:
-
如果此时线程池中的数量⼩于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
-
如果此时线程池中的数量等于corePoolSize,但是缓冲队列workQueue未满,那么任务被放⼊缓冲队列。
-
如果此时线程池中的数量⼤于等于corePoolSize,缓冲队列workQueue满,并且线程池中的数量⼩于maximumPoolSize,建新的线程来处理被添加的任务。
-
如果此时线程池中的数量⼤于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。
-
当线程池中的线程数量⼤于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终⽌。这样,线程池可以动态的调整池中的线程数
FixedThreadPool代表定⻓线程池,底层⽤的LinkedBlockingQueue,表示⽆界的阻塞队列。
6、sychronized和ReentrantLock的区别
-
sychronized是⼀个关键字,ReentrantLock是⼀个类
-
sychronized会⾃动的加锁与释放锁,ReentrantLock需要程序员⼿动加锁与释放锁
-
sychronized的底层是JVM层⾯的锁,ReentrantLock是API层⾯的锁
-
sychronized是⾮公平锁,ReentrantLock可以选择公平锁或⾮公平锁
-
sychronized锁的是对象,锁信息保存在对象头中,ReentrantLock通过代码中int类型的state标识来标识锁的状态
-
sychronized底层有⼀个锁升级的过程
7、sychronized的⾃旋锁、偏向锁、轻量级锁、重量级锁,分别介绍和联系
-
偏向锁:在锁对象的对象头中记录⼀下当前获取到该锁的线程ID,该线程下次如果⼜来获取该锁就可以直接获取到了
-
轻量级锁:由偏向锁升级⽽来,当⼀个线程获取到锁后,此时这把锁是偏向锁,此时如果有第⼆个线程来竞争锁,偏向锁就会升级为轻量级锁,之所以叫轻量级锁,是为了和重量级锁区分开来,轻量级锁底层是通过⾃旋来实现的,并不会阻塞线程
-
如果⾃旋次数过多仍然没有获取到锁,则会升级为重量级锁,重量级锁会导致线程阻塞
-
⾃旋锁:⾃旋锁就是线程在获取锁的过程中,不会去阻塞线程,也就⽆所谓唤醒线程,阻塞和唤醒这两个步骤都是需要操作系统去进⾏的,⽐较消耗时间,⾃旋锁是线程通过CAS获取预期的⼀个标记,如果没有获取到,则继续循环获取,如果获取到了则表示获取到了锁,这个过程线程⼀直在运⾏中,相对⽽⾔没有使⽤太多的操作系统资源,⽐较轻量。
8、HTTPS是如何保证安全传输的
https通过使⽤对称加密、⾮对称加密、数字证书等⽅式来保证数据的安全传输。
-
客户端向服务端发送数据之前,需要先建⽴TCP连接,所以需要先建⽴TCP连接,建⽴完TCP连接后,服务端会先给客户端发送公钥,客户端拿到公钥后就可以⽤来加密数据了,服务端到时候接收到数据就可以⽤私钥解密数据,这种就是通过⾮对称加密来传输数据
-
不过⾮对称加密⽐对称加密要慢,所以不能直接使⽤⾮对称加密来传输请求数据,所以可以通过⾮对称加密的⽅式来传输对称加密的秘钥,之后就可以使⽤对称加密来传输请求数据了
-
但是仅仅通过⾮对称加密+对称加密还不⾜以能保证数据传输的绝对安全,因为服务端向客户端发送公钥时,可能会被截取
-
所以为了安全的传输公钥,需要⽤到数字证书,数字证书是具有公信⼒、⼤家都认可的,服务端向客户端发送公钥时,可以把公钥和服务端相关信息通过Hash算法⽣成消息摘要,再通过数字证书提供的私钥对消息摘要进⾏加密⽣成数字签名,在把没进⾏Hash算法之前的信息和数字签名⼀起形成数字证书,最后把数字证书发送给客户端,客户端收到数字证书后,就会通过数字证书提供的公钥来解密数字证书,从⽽得到⾮对称加密要⽤到的公钥。
-
在这个过程中,就算有中间⼈拦截到服务端发出来的数字证书,虽然它可以解密得到⾮对称加密要使⽤的公钥,但是中间⼈是办法伪造数字证书发给客户端的,因为客户端上内嵌的数字证书是全球具有公信⼒的,某个⽹站如果要⽀持https,都是需要申请数字证书的私钥的,中间⼈如果要⽣成能被客户端解析的数字证书,也是要申请私钥的,所以是⽐较安全了。
蚂蚁二面
1、设计模式有哪些⼤类,及熟悉其中哪些设计模式
设计模式分为三⼤类:
1. 创建型
a. ⼯⼚模式(Factory Pattern)
b. 抽象⼯⼚模式(Abstract Factory Pattern)
c. 单例模式(Singleton Pattern)
d. 建造者模式(Builder Pattern)
e. 原型模式(Prototype Pattern)
2. 结构型
a. 适配器模式(Adapter Pattern)
b. 桥接模式(Bridge Pattern)
c. 过滤器模式(Filter、Criteria Pattern)
d. 组合模式(Composite Pattern)
e. 装饰器模式(Decorator Pattern)
f. 外观模式(Facade Pattern)
g. 享元模式(Flyweight Pattern)
h. 代理模式(Proxy Pattern)
3. ⾏为型
a. 责任链模式(Chain of Responsibility Pattern)
b. 命令模式(Command Pattern)
c. 解释器模式(Interpreter Pattern)
d. 迭代器模式(Iterator Pattern)
e. 中介者模式(Mediator Pattern)
f. 备忘录模式(Memento Pattern)
g. 观察者模式(Observer Pattern)
h. 状态模式(State Pattern)
i. 空对象模式(Null Object Pattern)
j. 策略模式(Strategy Pattern)
k. 模板模式(Template Pattern)
l. 访问者模式(Visitor Pattern)
2、volatile关键字,他是如何保证可⻅性,有序性
-
对于加了volatile关键字的成员变量,在对这个变量进⾏修改时,会直接将CPU⾼级缓存中的数据写回到主内存,对这个变量的读取也会直接从主内存中读取,从⽽保证了可⻅性
-
在对volatile修饰的成员变量进⾏读写时,会插⼊内存屏障,⽽内存屏障可以达到禁⽌重排序的效果,从⽽可以保证有序性
3、Java的内存结构,堆分为哪⼏部分,默认年龄多⼤进⼊⽼年代
1. 年轻代
a. Eden区(8)
b. From Survivor区(1)
c. To Survivor区(1)
2. ⽼年代
默认对象的年龄达到15后,就会进⼊⽼年代
4、Mysql的锁你了解哪些
按锁粒度分类:
-
⾏锁:锁某⾏数据,锁粒度最⼩,并发度⾼
-
表锁:锁整张表,锁粒度最⼤,并发度低
-
间隙锁:锁的是⼀个区间
还可以分为:
-
共享锁:也就是读锁,⼀个事务给某⾏数据加了读锁,其他事务也可以读,但是不能写
-
排它锁:也就是写锁,⼀个事务给某⾏数据加了写锁,其他事务不能读,也不能写
还可以分为:
-
乐观锁:并不会真正的去锁某⾏记录,⽽是通过⼀个版本号来实现的
-
悲观锁:上⾯所的⾏锁、表锁等都是悲观锁
在事务的隔离级别实现中,就需要利⽤所来解决幻读