一 Core Java:(P6级必问其中3题以上)
1. 整数数组按绝对值排序
List list = (List) Arrays.asList(array).stream().map(v->Math.abs(v)).sorted().collect(Collectors.toList());
2. ConcurrentHashMap 的数据结构
jdk1.6 segment数组 16个, 每个中 又一个hashbucket ,桶中每个元素 是个链接,即每个hash可能有多个key
jdk1.8 node node 中,hash,k,v,next ,
数组 +链表
3. 非阻塞IO和异步IO的区别
非阻塞io: 用户调用读写方法是不阻塞的,立刻返回,轮询内核进程,如果就绪,则拷贝数据到用户进程,并返回,拷贝操作用户来做
异步io: 用户线程不需关注读写,只需提供回调操作,内核线程完成读写之后回调用户提供的callback , 拷贝操作内核来做
阻塞:
多路复用:
除了异步,其他实际都是同步,判断标准就是实际io的时候,用户线程是否阻塞
用户进程内核进程
4. 内存管理机制,如何回收过期对象,判断依据,内存溢出场景,如何排查等等(P7需要很清楚的知道jvm的内存结构,回收过程,及虚拟机相关的回收算法及设计初衷)
内存结构: 堆(年轻代(eden spaces,survior spaces),老年代),虚拟机栈(每个线程独享一块栈内存),本地方法区,寄存器,堆外内存
回收过程:
1. eden spaces, 回收之后,存活的 进survior spaces,所以每次回收都会清空
2. survior spaces 满了以后回收,存活的进老年代
3. 大对象直接进入老年代
回收算法: 引用法 (实际不会使用引用法,因为回收解决循环引用对象)
根搜索法
内存管理: 1. 新建的对象 在堆 2. 基本数据类型在栈,线程 的内存在栈,
如何回收
5. equals和==的区别
6. final和finally
7. 常用的集合类有哪些?区别是什么?hashmap和hashtable的区别。哪些是线程安全的哪些不是?
线程安全的:vector,hashtable,enumeration,statck
8. Object中的常见的方法。
hashCode,equals,clone,toString,notify,notifyAll,wait,finalize
9. java中的异常体系,异常出现的情况如:ClassNotFound、空指针等
Java的异常类层次结构
ERROR virtulMachineError outofmemoryerror, stackoverFlowError
throwable ->
Exception ioExceptioneof,flienotfound
RuntimeException null,indexoutof,illegalArgument
10. JVM的内存模型是怎么样的?应用突然变得很慢,如何定位?
堆(年轻代(eden spaces,survior spaces),老年代),虚拟机栈(每个线程独享一块栈内存),方法区,寄存器,堆外内存
11. 对JDK8的新特性有什么了解
Lamada,函数式接口,流式操作,接口的默认和静态方法,方法引用,Optional
12. Java的类加载器的机制((P7除了知道机制外,需要能够说明,利用classloader特性的一些场景应用 )
机制: 将class文件导入内存,对数据校验,转换解析和初始化,最终形成可以被虚拟机直接使用的java类型
步骤:
(1) 装载:查找和导入Class文件
(2) 链接:把类的二进制数据合并到JRE中;
(a)校验:检查载入Class文件数据的正确性;
(b)准备:给类的静态变量分配存储空间;
(c)解析:将符号引用转成直接引用
(3) 初始化:对类的静态变量,静态代码块执行初始化操作
应用场景:
热部署(动态加载) ,OSGI
Java类从加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括,加载 ,验证, 准备, 解析, 初始化, 卸载 ,总共七个阶段。其中验证 ,准备, 解析 统称为连接。
而在解析阶段会有一个步将常量池当中二进制数据当中的符号引用转化为直接引用的过程。
符号引用 :符号引用以一组符号来描述所引用的目标。符号引用可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可,符号引用和虚拟机的布局无关。个人理解为:在编译的时候一个每个java类都会被编译成一个class文件,但在编译的时候虚拟机并不知道所引用类的地址,多以就用符号引用来代替,而在这个解析阶段就是为了把这个符号引用转化成为真正的地址的阶段。
public class Test{
public static void main() {
String s=”adc”;
System.out.println(“s=”+s);
}
}
13. 原子类的实现;
cas 无锁机制实现,非阻塞 先比较后交换
14. Error、Exception和RuntimeException的区别,作用又是什么
15. IO和NIO本质不同在实际项目使用场景及如何使用;
16. sleep() 和 wait() 有什么区别;
1. sleep是thread类的方法,wait是Object的方法
2. sleep 线程会让出cpu,但是不会释放对象锁
wait 会放弃对象锁
Stringbuilder 非线程安全
stringBuffer 线程安全的
二数据库&事物:(P6级必问)
1.什么样的场景会产生数据库死锁,如何解决
事务交叉
必然是由于环路等待引发的
下列方法有助于最大限度地降低死锁:
(1)按同一顺序访问对象。
(2)避免事务中的用户交互。
(3)保持事务简短并在一个批处理中。
(4)使用低隔离级别。
(5)使用绑定连接。
2.SQL如何优化
explain查看执行计划
1. 复杂查询中 不要使用like
2. 大数据查询 走索引
避免对索引字段进行计算操作
避免在索引字段上使用not,<>,!=
避免在索引列上使用IS NULL和IS NOT NULL (最好不要给数据库留NULL,尽可能的使用 NOT NULL填充数据库.)
避免在索引列上出现数据类型转换
避免在索引字段上使用函数
避免建立索引的列中使用空值。
在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,
否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致
3.where
避免在WHERE子句中使用in,not in,or或者having,可以使用 exist 和not exist代替 in和not in
避免在where子句中对字段进行函数操作
4. select
限制使用select * from table这种方式
5. 排序
避免使用耗费资源的操作,带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎 执行,耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序
6. 临时表
慎重使用临时表可以极大的提高系统性能
3.oracle或者mysql分页的实现思路
rownum
start ,limit
4.SQL怎么判断字段是否为空
SELECT * FROM fcs_nm.fcs_test1 where cust_name is null
SELECT * FROM fcs_nm.fcs_test1 where cust_name is not null
5.唯一索引能否插入空
不能,如果某列有多行包含 NULL 值,则不能在该列上创建唯一索引,
6.数据库索引的算法原理;
B树或者B+树
7.乐观锁,悲观锁;
悲观锁,每次拿数据认为别人可能修改,所以都加锁,别人等锁释放才能操作
乐观锁,认为每次拿别人都不会修改,但是更新的时候会判断一下期间是否有别人更改了数据,可使用版本号机制。
读的时候读出版本号,更新的时候版本号+1,判断提交的版本号大于db的版本号,则OK,否则说明数据被人改过
WEB(P6级必问)
post/get的区别是什么
Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE。URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个网络上的资源,而HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的查,改,增,删4个操作。到这里,大家应该有个大概的了解了,GET一般用于获取/查询资源信息,而POST一般用于更新资源信息
1.根据HTTP规范,GET用于信息获取,而且应该是安全的和幂等的。
(1).所谓安全的意味着该操作用于获取信息而非修改信息。换句话说,GET 请求一般不应产生副作用。就是说,它仅仅是获取资源信息,就像数据库查询一样,不会修改,增加数据,不会影响资源的状态。
* 注意:这里安全的含义仅仅是指是非修改信息。
(2).幂等的意味着对同一URL的多个请求应该返回同样的结果。这里我再解释一下幂等这个概念:
2.根据HTTP规范,POST表示可能修改变服务器上的资源的请求。继续引用上面的例子:还是新闻以网站为例,读者对新闻发表自己的评论应该通过POST实现,因为在评论提交后站点的资源已经不同了,或者说资源被修改了。
1.GET请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连,如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0%E5%A5%BD。如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII。
POST把提交的数据则放置在是HTTP包的包体中。
2."GET方式提交的数据最多只能是1024字节,理论上POST没有限制,可传较大量的数据,IIS4中最大为80KB,IIS5中为100KB"??!
以上这句是我从其他文章转过来的,其实这样说是错误的,不准确的,具体由服务器和操作系统决定
1. get是从服务器上获取数据,post是向服务器传送数据。
get 和 post只是一种传递数据的方式,get也可以把数据传到服务器,他们的本质都是发送请求和接收结果。只是组织格式和数据量上面有差别,http协议里面有介绍
2. get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。
因为get设计成传输小数据,而且最好是不修改服务器的数据,所以浏览器一般都在地址栏里面可以看到,但post一般都用来传递大数据,或比较隐私的数据,所以在地址栏看不到,能不能看到不是协议规定,是浏览器规定的。
3. 对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。
没明白,怎么获得变量和你的服务器有关,和get或post无关,服务器都对这些请求做了封装
4. get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。
post基本没有限制,我想大家都上传过文件,都是用post方式的。只不过要修改form里面的那个type参数
5. get安全性非常低,post安全性较高。
如果没有加密,他们安全级别都是一样的,随便一个监听器都可以把所有的数据监听到,不信你自己下一个监听网络资源的软件,
cookie/session有什么区别
web集群中登录态如何共享
redis
xss、csrf等如何防范?
xss: 跨站攻击
常见的,反射型注入,存储型注入
防范:(没有通用的答案,需要具体情况具体解析解决)
1. set-cookie加入httponly,禁止脚本读取和修改该cookie
2. 输入做检查,白名单控制关键字
3. 输出检查,比如使用安全的编码函数对输出内容编码
csrf :跨站点请求伪造
防范:
1.验证码
2. referer check
3. anti crsf token
sql注入如何防范?
SQL参数化
浏览器缓存策略;
Ajax如何解决跨域问题;
常用框架(P6级必问)
spring AOP/IOC的理解,大致原理,类内部调用是否会触发aop的逻辑?为什么?
aop 动态代理,
ioc,工厂设计模式
类内部调用是否会触发aop的逻辑,不会,因为拦截不到无从触发
Spring的事物传播属性 或 数据库的事物隔离级别,实现原理
事务隔离级
http://blog.csdn.net/willfcareer/article/details/5695530
数据库并发操作存在的异常情况:1. 更新丢失(Lost update):两个事务都同时更新一行数据但是第二个事务却中途失败退出导致对数据两个修改都失效了这是系统没有执行任何锁操作因此并发事务并没有被隔离开来。
2. 脏读取(Dirty Reads):一个事务开始读取了某行数据但是另外一个事务已经更新了此数据但没有能够及时提交。这是相当危险很可能所有操作都被回滚。
3. 不可重复读取(Non-repeatable Reads):一个事务对同一行数据重复读取两次但是却得到了不同结果。例如在两次读取中途有另外一个事务对该行数据进行了修改并提交。
4. 两次更新问题(Second lost updates problem):无法重复读取特例,有两个并发事务同时读取同一行数据然后其中一个对它进行修改提交而另一个也进行了修改提交这就会造成第一次写操作失效。
5. 幻读(Phantom Reads):也称为幻像(幻影)。事务在操作过程中进行两次查询,第二次查询结果包含了第一次查询中未出现的数据(这里并不要求两次查询SQL语句相同)这是因为在两次查询过程中有 另外一个事务插入数据造成的。
为了避免上面出现几种情况在标准SQL规范中定义了4个事务隔离级别,不同隔离级别对事务处理不同 。
1.未授权读取(Read Uncommitted):也称未提交读。允许脏读取但不允许更新丢失,如果一个事务已经开始写数据则另外一个数据则不允许同时进行写操作但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。事务隔离的最低级别,仅可保证不读取物理损坏的数据。与READ COMMITTED 隔离级相反,它允许读取已经被其它用户修改但尚未提交确定的数据。
2. 授权读取(Read Committed):也称提交读。允许不可重复读取但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现,读取数据的事务允许其他事务继续访问该行数据,但是未提交写事务将 会禁止其他事务访问该行。SQL Server 默认的级别。在此隔离级下,SELECT 命令不会返回尚未提交(Committed) 的数据,也不能返回脏数据。
3. 可重复读取(Repeatable Read):禁止不可重复读取和脏读取。但是有时可能出现幻影数据,这可以通过“共享读锁”和“排他写锁”实现,读取数据事务将会禁止写事务(但允许读事务),写事务则禁 止任何其他事务。在此隔离级下,用SELECT 命令读取的数据在整个命令执行过程中不会被更改。此选项会影响系统的效能,非必要情况最好不用此隔离级。
4. 串行(Serializable):也称可串行读。提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机 制保证新插入的数据不会被刚执行查询操作事务访问到。事务隔离的最高级别,事务之间完全隔离。如果事务在可串行读隔离级别上运行,则可以保证任何并发重叠 事务均是串行的。
隔离级别更新丢失脏读取重复读取幻读
未授权读取NYYY
授权读取NNYY
可重复读取NNNY
串行NNNN
velocity如何避免引用空属性的报错?
spring的单例或者原型如何配置?还用过其他什么scope?
scope=”prototype”
singleton=”false”
Single, Prototype,request,session,global session
log4j或者logback的日志记录文件在哪里?(开放式问题,怎么确定日志打到哪里了)
工具:
maven中如何排除包冲突。
使用mvn dependency:tree
使用exclusion排除冲突
svn合并代码怎么做
分布式:
如何实现分布式锁
http://blog.csdn.net/zdy0_2004/article/details/53070209
db,缓存,zk
基于redis的分布式锁
http://blog.csdn.net/ugg/article/details/41894947
缓存性能最佳,
zk 可靠性最佳 ,实现容易
@RequestMapping(value = "/lock", method = RequestMethod.GET)
@ResponseBody
public Object check() throws Exception {
for (int i = 0; i < 3; i++) {
final int k = i;
Thread t = new Thread(() -> {
String sigkey = "locktest0x0" + k;
suoTest("locktest0x0", sigkey, k);
});
t.start();
Thread.sleep(10);
}
return null;
}
private void suoTest(String key, String value, int k) {
boolean reValue = false;
do {
long t1 = System.currentTimeMillis();
reValue = jedisTemplate.setnx(key, Long.toString(t1));
System.out.println("key:" + key + ",获取锁:" + reValue);
if (reValue) {
// 执行业务
try {
long sleepTime = 1000;
if (k == 0) {
sleepTime = 1000 * 1000;
}
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
}
System.out.println("key:" + key + ":执行业务:" + value);
jedisTemplate.del(key);
System.out.println("key:" + key + ",释放锁");
} else {
// 判断是否超时,超时则删除(解锁)
String time = jedisTemplate.get(key);
if (null != time) {
long redisT = Long.parseLong(time);
long cha = t1 - redisT;
if (cha > 10000) {
System.out.println("发现超时准备解锁");
// 删除之前 需要重新获取锁 getSet
long t2 = System.currentTimeMillis();
String preTime = jedisTemplate.getSet(key, Long.toString(t2));
if (null == preTime) {
//
} else {
long actT = Long.parseLong(preTime);
if (actT == redisT) {
// 成功锁定
jedisTemplate.del(key);
System.out.println("解锁成功");
} else {
// 已经被其他人获取锁了
}
}
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
} while (!reValue);
}
分布式Session如何实现
如何消除分布式事物
MetaQ,Zookeeper 的原理和适用场景,(P7需要对业界的同类产品有一定的了解,知道各自的优缺点 )
Redis 3.0的分布式集群架构,(P7需要对业界的同类产品有一定的了解,知道各自的优缺点 )
Hash槽,每个节点设置使用部分如0-5000,5001-10000 ,便于扩展
高并发:
哨兵,提醒,自动故障迁移保证集群
原子计数器AtomicInteger的技术实现
无锁,cas,非阻塞
volatile的内存模型
线程内存(栈),主内存(堆) ,每次读的时候强制读住主内存中的值,而不是栈中的副本值
接口服务如何防止重复调用?
令牌法
自己使用过多线程的场景是什么?线程安全如何保证?java的并发框架是否用过,线程池是否用过,RejectedExecutionHandler是否知道?
刷起价,并发调用供应商,有1s内限制20个并发, 使用AtomicInteger 保住线程安全,采用丢弃策略(做好控制不会)
用了spring task ,
RejectedExecutionHandler,四种策略,丢弃,丢弃最老,中止抛出异常,直接执行。
设计:
对常用设计模式的了解,在项目中的实际应用。
单例(懒汉,饿汉),工厂模式,代理(动态代理AOP),观察者模式(ZK),命令链(spring过滤器,订座系统流程,ASC查询流程),适配器模式
懒汉:
public class SingletonClass{
private static SingletonClass instance=null;
public static synchronized SingletonClass getInstance(){
if(instance==null){
instance=new SingletonClass();
}
return instance;
}
private SingletonClass(){
}
}
饿汉:
public class Singleton{
//在自己内部定义自己的一个实例,只供内部调用
private static final Singleton instance = new Singleton();
private Singleton(){
//do something
}
//这里提供了一个供外部访问本class的静态方法,可以直接访问
public static Singleton getInstance(){
return instance;
}
}
双重锁
public class Singleton{
private static volatile Singleton instance=null;
private Singleton(){
//do something
}
public static Singleton getInstance(){
if(instance==null){
synchronized(SingletonClass.class){
if(instance==null){
instance=new Singleton();
}
}
}
return instance;
}
}
排序算法描述;
在项目中是否采用分层的结构,是怎样划分的,各层之间采用了哪些相关技术;
一般mvc模式,dao用mybatis,服务层 用redis ,zk,tsp做服务治理,多线程,spring 内存缓存, spring ,fastjson,logback,amq,quartz,hystrix(处理依赖隔离的框架)
场景问题:
对所做的系统的业务描述。能够描述清楚业务的核心逻辑和模型抽象,技术问题解决有正确思路(P6要求)。对其中的技术选型,技术方案有周全考虑,并且独立完成一个较复杂系统的设计和实现。(p7要求)
自己平时会学习些什么技术,学习程度如何?
做项目过程中遇到什么技术难点;(p6 和P7通过问题的技术难度、技术范围来区分);
分布式锁控制并发量,未解决,曲线救国了,通过缓存降低查询量,占位等随即等待时间重试
怎么看待加班;
线上问题分析处理是否有经验如何解决的
1. 业务代码bug
分析
2. db sql问题
sql慢查,分析binlog
3. 性能问题
看JVM监控,看内存,线程 ,cpu
抓thread dump, 查看线程有无死锁,大量blocked ,线程数是否正常,
dump堆,分析
P7除了要抽查上面的技术问题外,建议选择询问以下问题:
描述一个独立设计的较复杂系统的设计思路和实现,能够清晰表达系统中的关键概念模型,行业内的对标产品及相关技术的熟悉程度 。 ;
对其中的技术方案有周全考虑,技术方案完整无明显漏洞;
实际项目设计中的延展性,对业务未来发展有一定考虑;
实际项目设计中如何保持优雅,方便运维和发展;
独立设计系统中的技术选型的比较, 熟悉的技术领域最佳实践 ;
开发设计中,采取了什么样的技术手段,提高开发的效率;
如果要设计一个搜索引擎,像google那样只有两个页面,要求性能最大化,web方面应该如何设计?(不需要考虑搜索的逻辑)
项目中用到点的技术细节挖掘;主要考察他对技术细节深度理解。如对MetaQ原理的理解,同类产品的比较。
算法和数据结构的描述;展示他对各数据结构的理解,不同场景下如何设计合理的数据结构和算法,如何权衡时间与空间的取舍;
trouble shooting 的最佳实践 。 这里根据不同的trouble情况会涉及到jvm内存,数据库 ,操作系统等相关的知识点 。
目前团队的瓶颈和困难分析 。
碰到过的最棘手技术问题或最复杂的业务场景的设计 。
技术一面和二面的侧重点:
一面重点(从前到后):
技术能力,实际动手能力;
技术思路;
沟通表达能力;
学习能力;