最近一段时间考虑换个工作,通过猎头的推荐,发现深圳顺丰科技有个MyCat中间件研发工程师的职位挺适合我的,于是乎让她推荐了下简历,约了面试。约了电话面试。这里记录一下这次电话面试中流程以及被问到的一些问题:
首先面试官会让你做一个简单的介绍,我也没什么组织,没头没脑地介绍了自己的名字,学历,工作内容,由于对方招的是MyCat开发,所以在讲述相应的项目经历里面特别渲染了一下,介绍了自己对MyCat做了哪些工作。
接下来,就正式进入提问环节了:
1)你读过MySQL源代码么?
当时就傻眼了,我是搞Java的,MySQL源码可是C++代码。如实回答“没有”。
2)了解过MySQL的sql解析和路由解析么?
当场跪下了。也许是我在描述MyCat开发的项目经历表述不清楚,赶紧跟面试官解释:虽然我实现了MyCat的sql预处理功能需要了解MySQL协议包格式以及sql解析处理,但是跟MySQL源码确实没有关系,自己也没了解过MySQL的sql解析和路由解析。
接下来面试官就换话题了:“你从什么时候开始学的Java,从大学开始就学了吧?”, 我回答说“从大三开始就接触”,然后他就问了,“你主要擅长Java核心的哪一块?”。想了想,好像我也没有擅长哪一块呀!没办法,我就回答:“多线程吧”。紧接着是一堆多线程并发问题(估计他也是希望我回答这个- -。然后就可以虐死我了。):
3) Java实现同步的方式有哪些?
synchronized和Lock。
4) synchronized与Lock的区别是什么?
Lock有超时lock的机制,也支持中断,而synchronized没有,相比于synchronized,使用Lock具有更高的灵活性。
5) Lock的实现你知道哪些?
可重入锁(ReentrantLock,表示这个单词英文不会读- -。)
6) ReentrantLock的底层机制?
这个其实我也不知道该怎么回答,就回答了:基于CAS来实现,有公平锁和非公平锁,默认情况下创建的是非公平锁。
7) ReentrantLock的公平性与非公平性是怎么实现的?
当时真的不知道怎么回答,就直接跟面试官说不知道,但是他还是问了我,“如果要你来实现,你会怎么实现公平性和非公平性?”当时我就回答说:“应该是用一个队列来维护那些获取锁的线程,公平性的实现就是队列里面的元素先进的先出,有机会获取锁吧。非公平性可能是每个线程有个优先级,然后采用优先队列来实现吧。”
面试结束后看了ReentrantLock的源码发现,其实公平性和非公平性的差别体现在于对Sync类lock方法以及tryAcquire的实现上:
非公平锁对应使用NonfairSync,它的lock方法如下所示:
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}12345678910
非公平性首先体现在:
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());12
对于每一个调用lock方法的线程,均有可能先获取到锁,即使这个时候等待队列里面有其他正在等待锁的线程。这里体现了一个“插队”的概念,所以是非公平的(对于那些正在排队的等待线程来说)。
接下来,acquire会调用tryAcquire,tryAcquire最终调用nonfairTryAcquire:
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}12345678910111213141516171819202122
这里在c==0的条件分支里面也有非公平的实现:
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}123456
ReentrantLock内部确实会使用一个队列来保存那些等待获取锁的线程
8)死锁是怎么产生的?
不是很懂,举了个会产生死锁的例子给面试官听,描述得也不是很清楚。
9)如何避免死锁?
我回答说避免使用锁,还有尽量减少在占用一个共享资源的前提下再去占用另外一个共享资源。但是面试官好像还期待回答更多。
10)对concurrent包下面的容器类知道的有哪些?
回答了ArrayBlockingQueue和LinkedBlockingQueue(漏了ConcurrentHashMap - -。)
11)知道ConcurrentHashMap么?
赶紧回答知道。
12) ConcurrentHashMap的底层机制是怎么样的?
就我所知道的,ConcurrentHashMap分为多个Segment,一个Segment相当于一个ReentrantLock,即所谓的分段锁。放到ConcurrentHashMap的元素首先会被定位到某个Segment,一个Segment在底层实现相当于一个HashMap,也就是说ConcurrentHashMap内部维护了多个HashMap,并且具有线程安全性和并发访问性。
12) ConcurrentHashMap默认创建会初始化几个Segment?
16个
13)并发编程除了用锁来解决共享变量的访问,还有其他方式么?
不懂,面试官最后介绍了一个基于消息通信的模型框架(actor模型),好像是叫Akka,没了解过。
多线程并发的问题到这里又告一段落了,接下来问的是网络编程方面的东西:
13)对Java网络编程了解多少?
也没了解很多,主要是在接触MyCat的时候了解了一点NIO的知识。
14)那谈谈你对NIO的了解?
主要是在并发编程网上面看了相关的概念,NIO有3大概念:Channel、Buffer和Selector。NIO是多路复用IO,虽然说是非阻塞IO,但是还是会阻塞在Selector上面,Selector监听所有感兴趣的事件,比如新连接到来的事件、读事件以及写事件,通常我们将这些事件分发给工作线程去处理。
接下来他问了最后一个Java问题:
15)对Java内存了解多少?堆内内存和堆外内存?
我回答了对堆内存还稍微了解了一点,就是Java堆的分代以及GC算法。堆外内存没有了解过(应该是想问一些DirectHeap的东西,在网络编程里面涉及比较多)
最后还问了一个问题,因为他看我有用过HBase的经验,所以问了在项目使用HBase的过程中遇到什么问题?这里随便回答了一些,还好他没深入去问。
最后隐约是听到说另外找个时间面谈!
全部评论
(0) 回帖