2019独角兽企业重金招聘Python工程师标准>>>
贝壳金服目前的办公环境还可以,要人的渴望比较强烈,但是对基础的要求还是很高的。如果对java底层了解深刻,对框架理解透彻,那基本没啥问题。长话短说,看看这次我面试的三个小时都问了哪些问题。有些问题可能已经遗忘了,大多数我都在纸上划了一下,大体就是以下内容。-
1,AtomicInteger的实现原理。
CAS算法是由硬件直接支持来保证原子性的,有三个操作数:内存位置V、旧的预期值A和新值B,当且仅当V符合预期值A时,CAS用新值B原子化地更新V的值,否则,它什么都不做。
Unsafe的compareAndSwapInt是个native方法,也就是平台相关的。它是基于CPU的CAS指令来完成的。
2,CAS中ASA问题解决方案
方案1 加版本号
方案二用AtomicStampedReference解决ASA问题
private static class Pair { final T reference; final int stamp; private Pair(T reference, int stamp) { this.reference = reference; this.stamp = stamp; } static Pair of(T reference, int stamp) { return new Pair(reference, stamp); } } 这个类其实就是版本号的具体实现方案,通过Pair类里面的数据加版本号完美的解决ASA问题 3,CountDownLanch(倒计数锁存器)的应用和原理 class Driver2 { // … void main() throws InterruptedException { CountDownLatch doneSignal = new CountDownLatch(N); Executor e = …
for (int i = 0; i < N; ++i) // create and start threads
e.execute(new WorkerRunnable(doneSignal, i));
doneSignal.await(); // wait for all to finish
} }
class WorkerRunnable implements Runnable { private final CountDownLatch doneSignal; private final int i; WorkerRunnable(CountDownLatch doneSignal, int i) { this.doneSignal = doneSignal; this.i = i; } public void run() { try { doWork(i); doneSignal.countDown(); } catch (InterruptedException ex) {} // return; }
void doWork() { … } }
4,ThreadLocal 原理应用 public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); }
5,volatile关键字理解 多从可见性顺序性和原子性三个角度仔细阐述。对指令重排要有一定了解。 6,幂等运算 幂等我的理解是多次执行结果一致。
7,什么叫线程安全 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的。
8,数据库事务级别,隔离级别。这里面一定要记住要有场景性的理解,不能只知道概念 数据库得隔离级别是读未提交,读已提交,可重复读和串行化读
查询全局的事务隔离级别
SELECT @@global.tx_isolation;
查询当前会话的事务级别
SELECT @@session.tx_isolation; 脏读:脏读意味着我在这个事务中(A中),事务B虽然没有提交,但它任何一条数据变化,我都可以看到! 不可重复读(Nonrepeatable Read):不可重复读意味着我们在同一个事务中执行完全相同的select语句时可能看到不一样的结果。不可重复读是当事务A开启后读数据,当它未提交的时候,事务B开启,并更改了数据,那么A再读数据得时候已经不是之前的数据了。 可重复读:事务A开启后,读取了数据M,在事务A未提交的过程中,事务B开启了,并更改了数据M结构为N,当事务A再读数据得时候得到的还是数据M,只要事务A提交之后,才能够看到事务B更改了的数据N。 串行化读 (1)这是最高的隔离级别 (2)它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。 (3)在这个级别,可能导致大量的超时现象和锁竞争
9,什么是行级锁,全标锁 gap锁 什么时候产生? select … from语句:InnoDB引擎采用多版本并发控制(MVCC)的方式实现了非阻塞读,所以对于普通的select读语句,InnoDB并不会加锁【注1】。
select … from lock in share mode语句:这条语句和普通select语句的区别就是后面加了lock in share mode,通过字面意思我们可以猜到这是一条加锁的读语句,并且锁类型为共享锁(读锁)。InnoDB会对搜索的所有索引记录加next-key锁,但是如果扫描的唯一索引的唯一行,next-key降级为索引记录锁。
select … from for update语句:和上面的语句一样,这条语句加的是排他锁(写锁)。InnoDB会对搜索的所有索引记录加next-key锁,但是如果扫描唯一索引的唯一行,next-key降级为索引记录锁。
update … where …语句:。InnoDB会对搜索的所有索引记录加next-key锁,但是如果扫描唯一索引的唯一行,next-key降级为索引记录锁。【注2】
delete … where …语句:。InnoDB会对搜索的所有索引记录加next-key锁,但是如果扫描唯一索引的唯一行,next-key降级为索引记录锁。
insert语句:InnoDB只会在将要插入的那一行上设置一个排他的索引记录锁。
InnoDB引擎使用了七种类型的锁,他们分别是: 共享排他锁(Shared and Exclusive Locks) 有X锁不能再加S或者X锁,有S锁不能再加X锁或者S锁。 意向锁(Intention Locks) 记录锁(Record Locks) 间隙锁(Gap Locks) Next-Key Locks 插入意图锁(Insert Intention Locks) 自增锁(AUTO-INC Locks) 10,索引概念,知道几种索引
11,redis集群种类,要深入理解两类redis集群种类。
12,spring boot swagger
13,GCRoot JVM优化
14,阻塞队列,实现原理
15,深入理解AQS同步器
16,直接实现链表倒序 17,直接Controller线程安全么? servlet线程安全么? 这里面要记住,要想安全不要让这些东西保持有状态,一旦有状态就会涉及到线程不安全。 18,面向对象的三个基本特征 问到这个感觉已经是很远之前的事情了,封装,继承和多态
19,OCP是什么 面向修改关闭,面对扩展开放 Java的开闭原则
20 写一个程序找到链表的相交点
21,servlet组件组成 javaweb的三个组件servlet filter Lisener