1. Java线程的状态
Runnable状态与操作系统中进程运行状态的关系
2
. sleep和wait的区别
从资源层面来看,sleep占有哪些资源???
sleep不释放锁
什么是锁?
3
. 乐观锁与悲观锁
平时有没有用过乐观锁,怎么用的
CAS
4
. CAS原理。有用过CAS吗
5
. 什么是内存可见性,怎么保证的,可见性和原子性有什么关系?
6
. 解释一下
volatile
和
synchronized
,两者一样吗?
volatile
能保证线程安全吗?
7
. 索引的种类?什么是聚族索引?什么是覆盖索引?
8
. 数据库的隔离级别有哪些
9
. Redis出现多个Client同时修改redis服务器中同一个key怎么办?(redis并发竞争问题?)
10
. redis的事务跟数据库的事务一样吗?
11
. 一道算法题:
输入:
1
->
2
->
3
->….>n-
1
>n
输出:
1
->n->
2
->n-
1
->
3
->n-
2
…..
二面:
1
. JVM
2
. MVCC是什么?原理?
3
. 乐观锁与悲观锁
4
.
volatile
的原理?
volatile
有那些应用场景,写下代码
答:单例模式
写的代码:
public
class
Singleton {
private
Singleton(){}
private
volatile
static
Singleton instance;
public
static
Singleton getInstance() {
if
(instance ==
null
) {
synchronized
(Singleton.
class
) {
if
(instance ==
null
) {
instance =
new
Singleton();
}
}
}
return
instance;
}
}
问:为什么要使用
volatile
修饰。
答:为了防止指令重排序。
这行代码instance =
new
Singleton();实际上涉及到
3
个步骤
1
.分配内存空间
2
.初始化
3
.instance指向分配的内存空间
2
,
3
步骤是可以指令重排序的,如果不用
volatile
修饰,会造成
return
一个未初始化的instance
继续问:
synchronized
(Singleton.
class
)已经保证了获取这个类锁的只能有一个线程,为什么还会出现这种情况?结合具体例子分析一下?
答:????
(感觉他是想让我分析一下,在不用
volatile
情况下,线程A与线程B同时执行这部分代码,如何才能出现
return
一个未初始化的instance)
5
. 结合项目。
项目中的注册登录模块。能记住登录用户吗?怎么做到的?
Cookie与Session的区别?
服务端是怎么验证用户的?生成的token有可能重复吗?
客户端怎么存储token的?明文吗?如果被人截取怎么办,怎么保证安全性?
6
. TCP/IP与UDP什么关系?
TCP/IP是协议族,它的四层概念模型的传输层包含了UDP与TCP协议。
那TCP与UDP有什么区别?
UDP一对多怎么实现呢?
7
. 什么是平衡二叉数
答:我先讲了一下排序二叉树,有什么缺点,然后讲什么是平衡二叉树
再问:给了个具体例子:
10
8
16
6
9
这颗二叉树要新插入一个
5
怎么做?
答:
5
成为
6
的左孩子导致二叉树不平衡,要进行右旋转。
问:具体怎么旋转的,给你
15
分钟,代码实现一下
答:?????
8
. 算法题:k个有序链表合并。要求讲一下时间复杂度。
实习:最好在大四上学期的六、七月份(秋招提前批)之前积累所有实习,然后就可以密集面试->以小博大->复盘总结->经验+1了,本科生不打算读研就逃课去!!!(大三整个学期是最好的时间段,重要专业课可以b站自学),找实习的项目可以用mooc/mit/cmu/github上跟着学的 or 开发类比赛(一般和算法竞赛相悖,选了算法竞赛要天天刷题比赛,再去兼顾开发类很难。看你热爱和天赋,早做打算)的(仿中间件 or curd的话最好有分布式等加成),校招项目就加上实习公司的项目,而且实习一定要边实习边记录以免忘记内容和难点,因为很难一边实习一边秋招!要以小博大,先从不知名公司实习起;然后用小公司实习经验去博取大厂机会,可以大厂转正(转正很可能是白菜价),在部门呆的不满意就秋招。
比赛&项目:可以参加一些知名的比赛,如果参加了ICPC类基本大一大二就要天天刷题、打出成绩了(不是铁就可以,反正提高自己的算法能力,不打ICPC就刷LC)至少大三下学期必须实习;如果参加中间件、软件杯之类的,也要大一大二大三上参加,其余时间都是晚了的。项目的话最好是实习的项目,自己做的玩具面试官一般瞧不上。面经很多,找Java看这个https://www.nowcoder.com/discuss/344311?type=0&order=4&pos=25&page=3、https://www.nowcoder.com/discuss/331574?toCommentId=4824987;找cpp看这个https://www.nowcoder.com/discuss/338853?type=0&order=4&pos=5&page=2
校招:提前批、提前批、提前批(我就是因为实习(提供的住宿酒店信号不好就没怎么投)错过了6-8月的提前批后悔终身,离职后9月中才开始大投的,如果时间能重来,信女愿一生吃素);策略同样是以小博大,先找不想去的公司练手,再去面试大厂。
价格:这个我没argue过,因为没资格。不过这个估计是以大博小,用大厂白菜/sp博取中小厂sp/ssp吧。
忠告:你不是三个月就能成功(坚持、聪明、高学历)的大佬,而是间歇性踌躇满志,那就老老实实拉长时间线早做准备,不要以为临门一脚就能得到满意的结果!找当然能够找到,但是扪心自问,你觉得这是尽力后最好的结果吗?
自省:这都是血泪经验,本人踩过的坑有在算法竞赛上没有很大天赋、较吃力还去死磕,没有及时抽身而退,应该早点实习(这方面那个双非前端大佬家欣做的很好)从实践学习,不过当时还是有竞赛保研的侥幸在里面,也许选了哪条路都会后悔;提前批被【春招投太早导致大厂一轮游】吓怕了,所以秋招基本没投提前批,有些大厂也是因为怕冷冻期而投晚了,不过投早了估计也准备不到位而挂,没有早点实习真的一步错步步错。
一面(电话面)
在第一次面试中主要针对于之前所做的项目询问了一些细节。Java方面的问题则提问了Servelt的生命周期,线程的状态,加密算法(非对称,对称,MD5)以及数据库事务ACID四大特性。
二面(电话面)
在第二次面试中,面试官问到了Java的内存模型(原子性,有序性,可见性),ava中集合的层次,JVM的垃圾回收机制,HashMap、Hashtable、ConcurrentHashMap的区别,同步器实现机制。还问了我使用过哪些ORM框架,有一次问到了数据库事务的四大特性,还问了注解处理器,以及原子类底层机制(cas, Unsafe)以及快排实现方式。
三面(视频面)
第三次面试中,问了一些相关的技术问题了,主要问了ES的检索机制(query-then-fetch),其次还针对于一些具体的场景设定问了更多的问题,面试官问如果现在要搜一个词,按相关度排序,如何获取排名在(100-120)之间的文档,针对于“用户打车付款-滴滴后台-支付宝后台”设计一个一致性处理方案,此外还问了数据库事务特性以及隔离级别等。
看《Java并发编程艺术》随意记录摘抄一下
- 并发编程的目的:为了让程序运行的更快
但并不是启动更多的线程就能让程序最大限度的并发执行,因为这会面临线程上下文切换、死锁等问题。
-
如何减少上下文切换?
无锁并发编程、CAS算法、使用最少线程、使用协程。
-
并发编程中避免死锁的几个常见方法
-
避免一个线程同时获得多个锁
-
避免一个线程在锁内同时占有多个资源
-
尝试使用定时锁,使用 lock.tryLock(timeout) 来替代使用内部锁机制
-
对于数据库锁,加锁和解锁必须在同一个数据库连接里,否则会出现解锁失败的情况
-
-
volatile关键字的作用?
在多核处理器编程中保证了共享变量的可见性 -
volatile实现原理?
以X86处理器为例,在编译出来的汇编代码中,有带 Lock 前缀的指令。该指令会导致:
-
将当前处理器缓存行的数据写回到系统内存
-
一个处理器的缓存回写到内存会导致其它处理器的缓存无效
-
-
synchronized实现同步的基础:Java中的每一个对象都可以作为锁,具体表现为
-
对于普通同步方法,锁是当前实例对象
-
对于静态同步方法,锁是当前类的Class对象
-
对于同步代码块,锁是synchronized括号里配置的对象
-
-
synchronized用的锁存在于Java对象头
-
锁的几种状态
无锁状态、偏向锁、轻量级锁、重量级锁
锁可以升级但不能降级
-
偏向锁
-
目的:使线程获得锁的代价更低
-
当一个线程访问同步块获取锁时,会在对象头和栈帧的锁记录里存储锁偏向的线程ID,以后该线程进入和退出代码块时,不需要再用CAS进行加锁解锁,只需简单测试一下对象头的Mark Word里是否存储着指向当前线程的偏向锁。如果测试成功,表明该线程已经获得了锁;若测试失败,再测试Mark Word中偏向锁的标识是否设置为1(表明当前是偏向锁),如果没有设置,采用CAS算竞争锁;如果设置了,尝试使用CAS将对象头的偏向锁指向当前线程。
-
-
锁的优缺点对比
-
偏向锁:加锁和解锁不需额外的消耗;但如果线程间存在锁竞争,会带来额外的锁撤销的消耗;适用于只有一个线程访问同步块的场景
-
轻量级锁:竞争的线程不会阻塞,提高了线程的响应速度;但如果始终得不到锁竞争的线程,使用自旋会消耗CPU;适用场景:追求响应时间、同步代码块执行速度非常快
-
重量级锁:线程竞争不使用自旋,不消耗CPU;但线程阻塞,响应时间缓慢;适用场景:追求吞吐量、同步代码块执行时间较长
-
-
原子操作的实现原理
处理器如何实现原子操作?
- 通过总线锁保证原子性
- 通过缓存锁保证原子性
Java如何实现原子操作?
- 通过锁、循环CAS实现