一面感觉挺随便的,就是一大群人和一大群面试官在一个大房间然后一对一面试,俨然一个菜市场……也不知道有没有二面,面试官有些问题也没答上来,作为第一次面试还是好好记录一下,积累面试的套路经验
1、上来当然还是自我介绍
2、看简历,让我讲一下模仿天猫的项目用了什么技术栈,我主要用的SSM,就问了Spring的bean对象的生命周期。这个其实不是特别清楚,现在捋一下
流程图转自这篇博客
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iN2AjMxIDNxQzM1QTM4EzLcVDM0EDMy8CXxMjNwgTNvwVavwVbvNmLn9GbiRXauNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.png)
Bean的完整声明周期经过了很多方法调用,大致分为四个
- Bean自身的方法:包括Bean自身调用的方法以及applicationContext.xml中指定的init-method和destroy-method
- Bean级生命周期接口方法:这个包括了BeanNameAware,BeanFactoryAware,InitializingBean和DisposableBean这些接口的方法
- 容器级生命接口方法:这个包括InstantiationAwareBeanPostProcessor和BeanPostProcessor这两个接口,一般称它们的实现类为“后处理器”
- 工厂后处理器方法:这个包括AspectJWeavingEnabler,ConfigurationClassPostProcessor,CustomerAutowireConfigurer等工厂后处理器接口的方法,它也是容器级的,在应用上下文装配配置文件后立即调用
演示:
对照测试结果和流程图基本就清楚了
3、问项目是学校的还是单位的还是怎么的,我说是按照一个教程做的,就设想了一个并发场景,如果库存为1但同时有两人下单,那么会出现什么问题,如何解决。我一开始给的方案是给数据库加锁,同一时间只有一个用户能操作数据,他思考了一下说这样是可行的,但是又会带来另一个问题,如果此时库存加货了需要更新怎么办,让我回来思考。问了问站长他说可以用乐观锁来解决,大致就是采用一个版本控制,原理图如下
4、因为刚才讨论过程中我说到了也许可以用事务来解决(当然我是随便说的很快就反应到不对了)所以他又问了数据库的隔离级别, 这个没怎么看过,当时回答还跟springMVC的事务隔离级别混淆了,现在补上……
数据库的四种隔离级别
READ_UNCOMMITED
- 事务对当前读取的数据不加锁
- 事务在更新数据的瞬间必须对其加行级共享锁,直到事务结束才释放
表现
- 事务1读取某行记录时,事务2也能对这行记录进行读取、更新;当事务2对该记录进行更新时,事务1再次读取该记录,能读到事务2对该记录的修改版本,即使该修改尚未被提交
- 事务1更新某行记录时,事务2不能对这行记录做更新,直到事务1结束
READ_COMMITED
- 事务对当前读取到的数据加行级共享锁,一旦读完该行,立即释放锁
- 事务在更新某数据瞬间,必须加行级排他锁,直到事务结束才释放
表现
- 事务1读取某行记录时,事务2也能对这行记录进行读取、更新;当事务2对该记录进行更新时,事务1再次读取该记录,读到的只能是事务2对其更新前的版本,要不就是事务2提交后的版本
- 事务1更新某行记录时,事务2不能对这行记录做更新,直到事务1结束
REPEATABLE_READ
- 事务在读取某数据的瞬间(就是开始读取的瞬间),必须先对其加行级共享锁,直到事务结束才释放
- 事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加行级排他锁,直到事务结束才释放
表现
- 事务1读取某行记录时,事务2也能对这行记录进行读取、更新;当事务2对该记录进行更新时,事务1再次读取该记录,读到的仍然是第一次读取的那个版本
- 事务1更新某行记录时,事务2不能对这行记录做更新,直到事务1结束
SERIALIZABLE
- 事务在读取数据时,必须先对其加表级共享锁,直到事务结束才释放
- 事务在更新数据时,必须先对其加表级排他锁,直到事务结束才释放
表现
- 事务1正在读取A表中的记录时,则事务2也能读取A表,但不能对A表做更新、新增、删除,直到事务1结束
- 事务1正在更新A表中的记录时,则事务2不能读取A表的任意记录,更不可能对A表做更新、新增、删除,直到事务1结束
5、开始问Java基础,比如ArrayList和LinkedList的区别,插入较多选用哪个;HashMap和HashTable的区别,选用什么(我说ConcurrentHashMap)于是问了HashTable和ConcurrentHashMap线程安全的实现方式区别;然后还问了创建线程的两种方式,start和run的区别
6、问原子操作是什么意思,原子类是如何实现的。只记得原子类了,当时回答说可能都用了synchronized关键词,这里记一下
使用CAS算法,直接由硬件支持保证原子性
CAS记录三个值,内存位置V,预期值A,新值B
如果更新时发现V与A相等,则说明数据没有被修改过,就用B更新V,否则什么都不做
7、问了一些深入点的问题,用到什么设计模式(设计模式还没看,只能乱答)他提示我用过单例模式没有,我说用过,于是要求手写了一个单例(有点忘记了,估计当时写错了)这里巩固一下
三个要素
- 构造方法私有化,保证无法在外部new一个对象
- 静态属性指向实例
- public static的getInstance方法,返回第二步的静态属性
// 饿汉式,直接新建实例
public class Singleton {
private static Object instance = new Object();
private Singleton() {}
public static Object getInstance() {
return instance;
}
}
// 懒汉式,调用方法时才新建实例
public class Singleton {
private static Object instance;
private Singleton() {}
public static Object getInstance() {
if (null == instance)
instance = new Object();
return instance;
}
}
8、问JVM帮助我们优化了什么东西,举了个例子是回收内存。这个真的不知道怎么回答,毕竟没有深入研究过JVM……
9、看我是电气的,问我为什么转行,职业规划之类的
10、有什么问题要问我
差不多就这些,感觉自己答的不是太好,很多地方还有欠缺,没过也不觉得可惜吧。积攒经验,准备后面的面试