Android高级岗面试实战04——某二手交易平台Android电话一面
一开始我做了一下简单的自我介绍,然后开始大致说了一下自己的技术情况,面试小哥沿着我的技术栈问了几个很好的问题:
1.LRUCache污染问题如何避免?
我也不知道!
2.双检锁单例为什么线程不安全?
简单来说,就是JVM的指令重排!
public class DoubleCheckLock {
private static DoubleCheckLock instance;
private DoubleCheckLock() {
// TODO
}
public static DoubleCheckLock getInstance() {
if (instance == null) {
synchronized (DoubleCheckLock.class) {
if (instance == null) {
instance = new DoubleCheckLock();
}
}
}
return instance;
}
}
再回过头看我们的双检锁内部,对于"instance = new DoubleCheckLock();"这一行代码,它分为三个步骤执行:
1.分配一块内存空间
2.在这块内存上初始化一个DoubleCheckLock的实例
3.将声明的引用instance指向这块内存
第2和第3个步骤都依赖于第1个步骤,但是2和3之间没有依赖关系,那么如果编译器将2和3调换顺序,变成了:
1.分配一块内存空间
2.将声明的引用instance指向这块内存
3.在这块内存上初始化一个DoubleCheckLock的实例
当线程A执行到第2步时,instance已经不为null了,因为它指向了这块内存,此时如果线程B走到了"if (instance == null)",那么线程B其实拿到的还是一个null,因为这块内存还没有初始化,这就出现了问题。
解决方案:volatile关键字
public class DoubleCheckLock {
private static volatile DoubleCheckLock instance;
private DoubleCheckLock() {
// TODO
}
public static DoubleCheckLock getInstance() {
if (instance == null) {
synchronized (DoubleCheckLock.class) {
if (instance == null) {
instance = new DoubleCheckLock();
}
}
}
return instance;
}
}
3.OkHttp请求流程是什么?
https://www.jianshu.com/p/230e2e2988e0/
4.HashMap原理。
https://blog.csdn.net/vking_wang/article/details/14166593
5.EventBus如何做到进程间通信。
不清楚!~
6.详细讲一讲Http和Https。
7.数组和链表有什么区别?
数组存储区间是连续的,占用内存严重,故空间复杂度很大。但数组的二分查找时间复杂度小,为O(1);数组的特点是:寻址容易,插入和删除困难;
链表存储区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,达O(N)。链表的特点是:寻址困难,插入和删除容易。