基础篇html
基本功前端
六、说说反射的用途及实现java
八、HTTP 请求的 GET 与 POST 方式的区别node
十、session 分布式处理mysql
十二、MVC 设计思想react
1四、nginx
java自动装箱拆箱深刻剖析
谈谈Java反射机制
如何写一个不可变类?程序员
1七、Hashcode的做用,与 equal 有什么区别?web
a.一样用于鉴定2个对象是否相等的,java集合中有 list 和 set 两类,其中 set不容许元素重复实现,那个这个不容许重复实现的方法,若是用 equal 去比较的话,若是存在1000个元素,你 new 一个新的元素出来,须要去调用1000次 equal 去逐个和他们比较是不是同一个对象,这样会大大下降效率。hashcode其实是返回对象的存储地址,若是这个位置上没有元素,就把元素直接存储在上面,若是这个位置上已经存在元素,这个时候才去调用equal方法与新元素进行比较,相同的话就不存了,散列到其余地址上。面试
http://blog.csdn.net/lijiecao0226/article/details/24609559
2四、cloneable接口实现原理
2五、异常分类以及处理机制
3一、java中的异常:http://www.importnew.com/26613.html
3三、comparable与comparator的区别?
参考:http://www.cnblogs.com/szlbm/p/5504634.html
4二、.访问控制符public,protected,private,以及默认的区别
private只有在本类中才能访问;
public在任何地方都能访问;
protected在同包内的类及包外的子类能访问;
默认不写在同包内能访问。
4七、什么是泛型、为何要使用以及泛型擦除#
泛型,即“参数化类型”。
建立集合时就指定集合元素的类型,该集合只能保存其指定类型的元素,避免使用强制类型转换。
Java编译器生成的字节码是不包涵泛型信息的,泛型类型信息将在编译处理是被擦除,这个过程即类型擦除。泛型擦除能够简单的理解为将泛型java代码转换为普通java代码,只不过编译器更直接点,将泛型java代码直接转换成普通java字节码。
类型擦除的主要过程以下:
1).将全部的泛型参数用其最左边界(最顶级的父类型)类型替换。
2).移除全部的类型参数。
4八、.Error、Exception区别#
Error类和Exception类的父类都是throwable类,他们的区别是:
Error类通常是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。对于这类错误的致使的应用程序中断,仅靠程序自己没法恢复和和预防,遇到这样的错误,建议让程序终止。
Exception类表示程序能够处理的异常,能够捕获且可能恢复。遇到这类异常,应该尽量处理异常,使程序恢复运行,而不该该随意终止异常。
50、Java中如何实现代理机制(JDK、CGLIB)#
JDK动态代理:代理类和目标类实现了共同的接口,用到InvocationHandler接口。
CGLIB动态代理:代理类是目标类的子类,用到MethodInterceptor接口。
使用==比较原生类型如:boolean、int、char等等,使用equals()比较对象。
一、==是判断两个变量或实例是否是指向同一个内存空间。 equals是判断两个变量或实例所指向的内存空间的值是否是相同。
二、==是指对内存地址进行比较。 equals()是对字符串的内容进行比较。
三、==指引用是否相同。 equals()指的是值是否相同。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public static void main(String[] args) {
String a = new String( "ab" ); // a 为一个引用
String b = new String( "ab" ); // b为另外一个引用,对象的内容同样
String aa = "ab" ; // 放在常量池中
String bb = "ab" ; // 从常量池中查找
System.out.println(aa == bb); // true
System.out.println(a == b); // false,非同一对象
System.out.println(a.equals(b)); // true
System.out.println( 42 == 42.0 ); // true
}
public static void main(String[] args) {
Object obj1 = new Object();
Object obj2 = new Object();
System.out.println(obj1.equals(obj2)); //false
System.out.println(obj1==obj2); //false
obj1=obj2;
System.out.println(obj1==obj2); //true
System.out.println(obj2==obj1); //true
}
|
Object是全部类的父类,任何类都默认继承Object
clone 保护方法,实现对象的浅复制,只有实现了Cloneable接口才能够调用该方法,不然抛出CloneNotSupportedException异常。
equals 在Object中与==是同样的,子类通常须要重写该方法。
hashCode 该方法用于哈希查找,重写了equals方法通常都要重写hashCode方法。这个方法在一些具备哈希功能的Collection中用到。
getClass final方法,得到运行时类型
wait 使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具备该对象的锁。 wait() 方法一直等待,直到得到锁或者被中断。 wait(long timeout) 设定一个超时间隔,若是在规定时间内没有得到锁就返回。
调用该方法后当前线程进入睡眠状态,直到如下事件发生
一、其余线程调用了该对象的notify方法。 二、其余线程调用了该对象的notifyAll方法。 三、其余线程调用了interrupt中断该线程。 四、时间间隔到了。 五、此时该线程就能够被调度了,若是是被中断的话就抛出一个InterruptedException异常。
notify 唤醒在该对象上等待的某个线程。
notifyAll 唤醒在该对象上等待的全部线程。
toString 转换成字符串,通常子类都有重写,不然打印句柄。
从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。
一、强引用
最广泛的一种引用方式,如String s = "abc",变量s就是字符串“abc”的强引用,只要强引用存在,则垃圾回收器就不会回收这个对象。
二、软引用(SoftReference)
用于描述还有用但非必须的对象,若是内存足够,不回收,若是内存不足,则回收。通常用于实现内存敏感的高速缓存,软引用能够和引用队列ReferenceQueue联合使用,若是软引用的对象被垃圾回收,JVM就会把这个软引用加入到与之关联的引用队列中。
三、弱引用(WeakReference)
弱引用和软引用大体相同,弱引用与软引用的区别在于:只具备弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程当中,一旦发现了只具备弱引用的对象,无论当前内存空间足够与否,都会回收它的内存。
四、虚引用(PhantomReference)
就是形同虚设,与其余几种引用都不一样,虚引用并不会决定对象的生命周期。若是一个对象仅持有虚引用,那么它就和没有任何引用同样,在任什么时候候均可能被垃圾回收器回收。 虚引用主要用来跟踪对象被垃圾回收器回收的活动。
虚引用与软引用和弱引用的一个区别在于:
虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,若是发现它还有虚引,就会在回收对象的内存以前,把这个虚引用加入到与之关联的引用队列中。
http://blog.csdn.net/seu_calvin/article/details/52094115
一、HashCode的特性
(1)HashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,HashCode常常用于肯定对象的存储地址。
(2)若是两个对象相同,?equals方法必定返回true,而且这两个对象的HashCode必定相同。
(3)两个对象的HashCode相同,并不必定表示两个对象就相同,即equals()不必定为true,只可以说明这两个对象在一个散列存储结构中。
(4)若是对象的equals方法被重写,那么对象的HashCode也尽可能重写。
二、HashCode做用
Java中的集合有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素能够重复;后者元素无序,但元素不可重复。
equals方法可用于保证元素不重复,但若是每增长一个元素就检查一次,若集合中如今已经有1000个元素,那么第1001个元素加入集合时,就要调用1000次equals方法。这显然会大大下降效率。?因而,Java采用了哈希表的原理。
哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。
这样一来,当集合要添加新的元素时,先调用这个元素的HashCode方法,就一会儿能定位到它应该放置的物理位置上。
(1)若是这个位置上没有元素,它就能够直接存储在这个位置上,不用再进行任何比较了。
(2)若是这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了。
(3)不相同的话,也就是发生了Hash key相同致使冲突的状况,那么就在这个Hash key的地方产生一个链表,将全部产生相同HashCode的对象放到这个单链表上去,串在一块儿(不多出现)。
这样一来实际调用equals方法的次数就大大下降了,几乎只须要一两次。
如何理解HashCode的做用:
从Object角度看,JVM每new一个Object,它都会将这个Object丢到一个Hash表中去,这样的话,下次作Object的比较或者取这个对象的时候(读取过程),它会根据对象的HashCode再从Hash表中取这个对象。这样作的目的是提升取对象的效率。若HashCode相同再去调用equal。
三、HashCode实践(如何用来查找)
HashCode是用于查找使用的,而equals是用于比较两个对象是否相等的。
(1)例如内存中有这样的位置
0 1 2 3 4 5 6 7
而我有个类,这个类有个字段叫ID,我要把这个类存放在以上8个位置之一,若是不用HashCode而任意存放,那么当查找时就须要到这八个位置里挨个去找,或者用二分法一类的算法。
但以上问题若是用HashCode就会使效率提升不少 定义咱们的HashCode为ID%8,好比咱们的ID为9,9除8的余数为1,那么咱们就把该类存在1这个位置,若是ID是13,求得的余数是5,那么咱们就把该类放在5这个位置。依此类推。
(2)可是若是两个类有相同的HashCode,例如9除以8和17除以8的余数都是1,也就是说,咱们先经过?HashCode来判断两个类是否存放某个桶里,但这个桶里可能有不少类,那么咱们就须要再经过equals在这个桶里找到咱们要的类。
请看下面这个例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public class HashTest {
private int i;
public int getI() {
return i;
}
public void setI( int i) {
this .i = i;
}
public int hashCode() {
return i % 10 ;
}
public final static void main(String[] args) {
HashTest a = new HashTest();
HashTest b = new HashTest();
a.setI( 1 );
b.setI( 1 );
Set<HashTest> set = new HashSet<HashTest>();
set.add(a);
set.add(b);
System.out.println(a.hashCode() == b.hashCode());
System.out.println(a.equals(b));
System.out.println(set);
}
}
|
输出结果为:
1
2
3
|
true
False
[HashTest @1 , HashTest @1 ]
|
以上这个示例,咱们只是重写了HashCode方法,从上面的结果能够看出,虽然两个对象的HashCode相等,可是实际上两个对象并非相等,由于咱们没有重写equals方法,那么就会调用Object默认的equals方法,显示这是两个不一样的对象。
这里咱们将生成的对象放到了HashSet中,而HashSet中只可以存放惟一的对象,也就是相同的(适用于equals方法)的对象只会存放一个,可是这里其实是两个对象ab都被放到了HashSet中,这样HashSet就失去了他自己的意义了。
下面咱们继续重写equals方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
public class HashTest {
private int i;
public int getI() {
return i;
}
public void setI( int i) {
this .i = i;
}
public boolean equals(Object object) {
if (object == null ) {
return false ;
}
if (object == this ) {
return true ;
}
if (!(object instanceof HashTest)) {
return false ;
}
HashTest other = (HashTest) object;
if (other.getI() == this .getI()) {
return true ;
}
return false ;
}
public int hashCode() {
return i % 10 ;
}
public final static void main(String[] args) {
HashTest a = new HashTest();
HashTest b = new HashTest();
a.setI( 1 );
b.setI( 1 );
Set<HashTest> set = new HashSet<HashTest>();
set.add(a);
set.add(b);
System.out.println(a.hashCode() == b.hashCode());
System.out.println(a.equals(b));
System.out.println(set);
}
}
|
输出结果以下所示。
从结果咱们能够看出,如今两个对象就彻底相等了,HashSet中也只存放了一份对象。
注意:
hashCode()只是简单示例写的,真正的生产换将不是这样的
1
2
3
|
true
true
[HashTest @1 ]
|
hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中肯定对象的存储地址的。
若是两个对象相同,就是适用于equals(java.lang.Object) 方法,那么这两个对象的hashCode必定要相同。
若是对象的equals方法被重写,那么对象的hashCode也尽可能重写,而且产生hashCode使用的对象,必定要和equals方法中使用的一致,不然就会违反上面提到的第2点。
两个对象的hashCode相同,并不必定表示两个对象就相同,也就是不必定适用于equals(java.lang.Object) 方法,只可以说明这两个对象在散列存储结构中,如Hashtable,他们“存放在同一个篮子里”。
何时须要重写?
通常的地方不须要重载hashCode,只有当类须要放在HashTable、HashMap、HashSet等等hash结构的集合时才会重载hashCode,那么为何要重载hashCode呢?
要比较两个类的内容属性值,是否相同时候,根据hashCode 重写规则,重写类的 指定字段的hashCode(),equals()方法。
例如
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
public class EmpWorkCondition{
/**
* 员工ID
*/
private Integer empId;
/**
* 员工服务总单数
*/
private Integer orderSum;
@Override
public boolean equals(Object o) {
if ( this == o) {
return true ;
}
if (o == null || getClass() != o.getClass()) {
return false ;
}
EmpWorkCondition that = (EmpWorkCondition) o;
return Objects.equals(empId, that.empId);
}
@Override
public int hashCode() {
return Objects.hash(empId);
}
// 省略 getter setter
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public static void main(String[] args) {
List<EmpWorkCondition> list1 = new ArrayList<EmpWorkCondition>();
EmpWorkCondition emp1 = new EmpWorkCondition();
emp1.setEmpId( 100 );
emp1.setOrderSum( 90000 );
list1.add(emp1);
List<EmpWorkCondition> list2 = new ArrayList<EmpWorkCondition>();
EmpWorkCondition emp2 = new EmpWorkCondition();
emp2.setEmpId( 100 );
list2.add(emp2);
System.out.println(list1.contains(emp2));
}
|
输出结果:true
上面的方法,作的事情就是,比较两个集合中的,实体类对象属性值,是否一致
OrderSum 不在比较范围内,由于没有重写它的,equals()和hashCode()方法
为何要重载equal方法?
由于Object的equal方法默认是两个对象的引用的比较,意思就是指向同一内存,地址则相等,不然不相等;若是你如今须要利用对象里面的值来判断是否相等,则重载equal方法。
通常的地方不须要重载hashCode,只有当类须要放在HashTable、HashMap、HashSet等等hash结构的集合时才会重载hashCode,那么为何要重载hashCode呢?
若是你重写了equals,好比说是基于对象的内容实现的,而保留hashCode的实现不变,那么极可能某两个对象明明是“相等”,而hashCode却不同。
这样,当你用其中的一个做为键保存到hashMap、hasoTable或hashSet中,再以“相等的”找另外一个做为键值去查找他们的时候,则根本找不到。
为何equals()相等,hashCode就必定要相等,而hashCode相等,却不要求equals相等?
一、由于是按照hashCode来访问小内存块,因此hashCode必须相等。 二、HashMap获取一个对象是比较key的hashCode相等和equal为true。
之因此hashCode相等,却能够equal不等,就好比ObjectA和ObjectB他们都有属性name,那么hashCode都以name计算,因此hashCode同样,可是两个对象属于不一样类型,因此equal为false。
为何须要hashCode?
一、经过hashCode能够很快的查到小内存块。 二、经过hashCode比较比equal方法快,当get时先比较hashCode,若是hashCode不一样,直接返回false。
5九、Java对象的生命周期
答:建立阶段 、 应用阶段 、不可见阶段 、不可达阶段 、收集阶段 、终结阶段、 对象空间从新分配阶段等等,具体参照:Java 对象的生命周期
答:Java event时间监听 ,即在set方法改变属性时,触发 ,这种模式也能够理解为观察者模式,具体查看:观察者模式简单案例和说明
集合
八、HashMap 的工做原理及代码实现
十、HashMap与HashTable的区别。
一、HashMap是非线程安全的,HashTable是线程安全的。
二、HashMap的键和值都容许有null值存在,而HashTable则不行。
三、由于线程安全的问题,HashMap效率比HashTable的要高。
HashMap的实现机制:
维护一个每一个元素是一个链表的数组,并且链表中的每一个节点是一个Entry[]键值对的数据结构。
实现了数组+链表的特性,查找快,插入删除也快。
对于每一个key,他对应的数组索引下标是 int i = hash(key.hashcode)&(len-1);
每一个新加入的节点放在链表首,而后该新加入的节点指向原链表首
HashMap和TreeMap区别
友情连接: Java中HashMap和TreeMap的区别深刻理解
HashMap冲突
友情连接: HashMap冲突的解决方法以及原理分析
十一、HashMap,ConcurrentHashMap与LinkedHashMap的区别
ConcurrentHashMap是使用了锁分段技术技术来保证线程安全的,锁分段技术:首先将数据分红一段一段的存储,而后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其余段的数据也能被其余线程访问
ConcurrentHashMap 是在每一个段(segment)中线程安全的
LinkedHashMap维护一个双链表,能够将里面的数据按写入的顺序读出
ConcurrentHashMap应用场景
1:ConcurrentHashMap的应用场景是高并发,可是并不能保证线程安全,而同步的HashMap和HashMap的是锁住整个容器,而加锁以后ConcurrentHashMap不须要锁住整个容器,只须要锁住对应的Segment就行了,因此能够保证高并发同步访问,提高了效率。
2:能够多线程写。
ConcurrentHashMap把HashMap分红若干个Segmenet
1.get时,不加锁,先定位到segment而后在找到头结点进行读取操做。而value是volatile变量,因此能够保证在竞争条件时保证读取最新的值,若是读到的value是null,则可能正在修改,那么就调用ReadValueUnderLock函数,加锁保证读到的数据是正确的。
2.Put时会加锁,一概添加到hash链的头部。
3.Remove时也会加锁,因为next是final类型不可改变,因此必须把删除的节点以前的节点都复制一遍。
4.ConcurrentHashMap容许多个修改操做并发进行,其关键在于使用了锁分离技术。它使用了多个锁来控制对Hash表的不一样Segment进行的修改。
ConcurrentHashMap的应用场景是高并发,可是并不能保证线程安全,而同步的HashMap和HashTable的是锁住整个容器,而加锁以后ConcurrentHashMap不须要锁住整个容器,只须要锁住对应的segment就行了,因此能够保证高并发同步访问,提高了效率。
ConcurrentHashMap可以保证每一次调用都是原子操做,可是并不保证屡次调用之间也是原子操做。
友情连接:Java集合—ConcurrentHashMap原理分析
十二、
Vector和ArrayList的区别
友情连接:Java中Vector和ArrayList的区别
1四、
HashMap的底层实现,以后会问ConcurrentHashMap的底层实现;
2四、HashMap 是线程安全的吗,为何不是线程安全的(最好画图说明多线程环境下不安全)?
2五、HashMap 的扩容过程
2六、HashMap 1.7 与 1.8 的 区别,说明 1.8 作了哪些优化,如何优化的?
2九、LinkedHashMap的应用:LRU算法
31. ConcurrentHashMap
的实现原理
A:它是一个对写操做加了锁的HashMap
,不一样的是它作了二次分割,元素被存储在不一样的桶里,以见效锁的数据范围,提高性能。
在JDK8中对这种实现又进行了修改,JDK8中的ConcurrentHashmap
基于CAS和TreeBin
实现的,不须要对segment或者全局加锁,只须要对单行枷锁(hashCode相同),后边的链表是链表加红黑树。对于单个值的修改使用CAS。
面试官极可能想听到的是这样,但这里重要的是分治的概念。其实彻底可让候选人尝试本身去设计一个ConcurrentHashMap
,而后引导他去拆分HashMap
,这样才是正道啊。
32. TransferQueue
的算法是什么样的,它和BlockingQueue
有哪些不一样
33. Arraylist与LinkedList的比较
一、ArrayList是实现了基于动态数组的数据结构,由于地址连续,一旦数据存储好了,查询操做效率会比较高(在内存里是连着放的)。
二、由于地址连续, ArrayList要移动数据,因此插入和删除操做效率比较低。
三、LinkedList基于链表的数据结构,地址是任意的,因此在开辟内存空间的时候不须要等一个连续的地址,对于新增和删除操做add和remove,LinedList比较占优点。
四、由于LinkedList要移动指针,因此查询操做性能比较低。
适用场景分析:
当须要对数据进行随机访问的状况下选用ArrayList,当须要对数据进行屡次增长删除修改时采用LinkedList。
34. ArrayList与Vector的比较
一、Vector的方法都是同步的,是线程安全的,而ArrayList的方法不是,因为线程的同步必然要影响性能。所以,ArrayList的性能比Vector好。
二、当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增长50%的大小,这样。ArrayList就有利于节约内存空间。
三、大多数状况不使用Vector,由于性能很差,可是它支持线程的同步,即某一时刻只有一个线程可以写Vector,避免多线程同时写而引发的不一致性。
四、Vector能够设置增加因子,而ArrayList不能够。
适用场景分析:
一、Vector是线程同步的,因此它也是线程安全的,而ArrayList是线程异步的,是不安全的。若是不考虑到线程的安全因素,通常用ArrayList效率比较高。
二、若是集合中的元素的数目大于目前集合数组的长度时,在集合中使用数据量比较大的数据,用Vector有必定的优点。
35.HashSet与TreeSet的比较
1.TreeSet 是二叉树实现的,Treeset中的数据是自动排好序的,不容许放入null值 。
2.HashSet 是哈希表实现的,HashSet中的数据是无序的,能够放入null,但只能放入一个null,二者中的值都不能重复,就如数据库中惟一约束 。
3.HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码做为标识的,而具备相同内容的String对象,hashcode是同样,因此放入的内容不能重复。可是同一个类的对象能够放入不一样的实例。
适用场景分析:
HashSet是基于Hash算法实现的,其性能一般都优于TreeSet。咱们一般都应该使用HashSet,在咱们须要排序的功能时,咱们才使用TreeSet。
36. HashMap和ConcurrentHashMap的区别
一、HashMap不是线程安全的,而ConcurrentHashMap是线程安全的。
二、ConcurrentHashMap采用锁分段技术,将整个Hash桶进行了分段segment,也就是将这个大的数组分红了几个小的片断segment,并且每一个小的片断segment上面都有锁存在,那么在插入元素的时候就须要先找到应该插入到哪个片断segment,而后再在这个片断上面进行插入,并且这里还须要获取segment锁。
三、ConcurrentHashMap让锁的粒度更精细一些,并发性能更好。
37. HashTable和ConcurrentHashMap的区别
它们均可以用于多线程的环境,可是当Hashtable的大小增长到必定的时候,性能会急剧降低,由于迭代时须要被锁定很长的时间。由于ConcurrentHashMap引入了分割(segmentation),不论它变得多么大,仅仅须要锁定map的某个部分,而其它的线程不须要等到迭代完成才能访问map。简而言之,在迭代的过程当中,ConcurrentHashMap仅仅锁定map的某个部分,而Hashtable则会锁定整个map。
3六、java中的集合类:http://www.javashuo.com/article/p-xtnpuchz-bp.html
3七、HashMap与HashTable、ConcurrentHashMap区别:http://www.javashuo.com/article/p-shzydloe-gu.html
3九、Arrays和Collections 对于sort的不一样实现原理?
一、Arrays.sort()
该算法是一个通过调优的快速排序,此算法在不少数据集上提供N*log(N)的性能,这致使其余快速排序会下降二次型性能。
二、Collections.sort()
该算法是一个通过修改的合并排序算法(其中,若是低子列表中的最高元素效益高子列表中的最低元素,则忽略合并)。此算法可提供保证的N*log(N)的性能,此实现将指定列表转储到一个数组中,而后再对数组进行排序,在重置数组中相应位置处每一个元素的列表上进行迭代。
40、HashMap的源码,实现原理,JDK8中对HashMap作了怎样的优化。
4一、HaspMap扩容是怎样扩容的,为何都是2的N次幂的大小。
4三、极高并发下HashTable和ConcurrentHashMap哪一个性能更好,为何,如何实现的。
4六、HashMap实现原理#
具体原理参考文章:
http://zhangshixi.iteye.com/blog/672697
http://www.admin10000.com/document/3322.html
4七、HashTable实现原理#
具体原理参考文章:
http://www.cnblogs.com/skywang12345/p/3310887.html
http://blog.csdn.net/chdjj/article/details/38581035
4八、HashMap和HashTable区别#
1)HashTable的方法前面都有synchronized来同步,是线程安全的;HashMap未经同步,是非线程安全的。
2)HashTable不容许null值(key和value都不能够) ;HashMap容许null值(key和value均可以)。
3)HashTable有一个contains(Object value)功能和containsValue(Object value)功能同样。
4)HashTable使用Enumeration进行遍历;HashMap使用Iterator进行遍历。
5)HashTable中hash数组默认大小是11,增长的方式是old*2+1;HashMap中hash数组的默认大小是16,并且必定是2的指数。
6)哈希值的使用不一样,HashTable直接使用对象的hashCode; HashMap从新计算hash值,并且用与代替求模。
5二、.Concurrenthashmap实现原理#
具体原理参考文章:
http://www.cnblogs.com/ITtangtang/p/3948786.html
http://ifeve.com/concurrenthashmap/
5五、HashMap和HashTable的区别
https://segmentfault.com/a/1190000008101567
总结
JDK6,7中的ConcurrentHashmap主要使用Segment来实现减少锁粒度,把HashMap分割成若干个Segment,在put的时候须要锁住Segment,get时候不加锁,使用volatile来保证可见性,当要统计全局时(好比size),首先会尝试屡次计算modcount来肯定,这几回尝试中,是否有其余线程进行了修改操做,若是没有,则直接返回size。若是有,则须要依次锁住全部的Segment来计算。
jdk7中ConcurrentHashmap中,当长度过长碰撞会很频繁,链表的增改删查操做都会消耗很长的时间,影响性能。
jdk8 中彻底重写了concurrentHashmap,代码量从原来的1000多行变成了 6000多 行,实现上也和原来的分段式存储有很大的区别。
JDK8中采用的是位桶+链表/红黑树(有关红黑树请查看红黑树)的方式,也是非线程安全的。当某个位桶的链表的长度达到某个阀值的时候,这个链表就将转换成红黑树。
JDK8中,当同一个hash值的节点数不小于8时,将再也不以单链表的形式存储了,会被调整成一颗红黑树(上图中null节点没画)。这就是JDK7与JDK8中HashMap实现的最大区别。
主要设计上的变化有如下几点
1.jdk8不采用segment而采用node,锁住node来实现减少锁粒度。 2.设计了MOVED状态 当resize的中过程当中 线程2还在put数据,线程2会帮助resize。 3.使用3个CAS操做来确保node的一些操做的原子性,这种方式代替了锁。 4.sizeCtl的不一样值来表明不一样含义,起到了控制的做用。
至于为何JDK8中使用synchronized而不是ReentrantLock,我猜是由于JDK8中对synchronized有了足够的优化吧。
ConcurrentHashMap能彻底替代HashTable吗
hashTable虽然性能上不如ConcurrentHashMap,但并不能彻底被取代,二者的迭代器的一致性不一样的,hash table的迭代器是强一致性的,而concurrenthashmap是弱一致的。
ConcurrentHashMap的get,clear,iterator 都是弱一致性的。 Doug Lea 也将这个判断留给用户本身决定是否使用ConcurrentHashMap。
ConcurrentHashMap与HashTable均可以用于多线程的环境,可是当Hashtable的大小增长到必定的时候,性能会急剧降低,由于迭代时须要被锁定很长的时间。由于ConcurrentHashMap引入了分割(segmentation),不论它变得多么大,仅仅须要锁定map的某个部分,而其它的线程不须要等到迭代完成才能访问map。简而言之,在迭代的过程当中,ConcurrentHashMap仅仅锁定map的某个部分,而Hashtable则会锁定整个map。
那么既然ConcurrentHashMap那么优秀,为何还要有Hashtable的存在呢?ConcurrentHashMap能彻底替代HashTable吗?
HashTable虽然性能上不如ConcurrentHashMap,但并不能彻底被取代,二者的迭代器的一致性不一样的,HashTable的迭代器是强一致性的,而ConcurrentHashMap是弱一致的。 ConcurrentHashMap的get,clear,iterator 都是弱一致性的。 Doug Lea 也将这个判断留给用户本身决定是否使用ConcurrentHashMap。
那么什么是强一致性和弱一致性呢?
get方法是弱一致的,是什么含义?可能你指望往ConcurrentHashMap底层数据结构中加入一个元素后,立马能对get可见,但ConcurrentHashMap并不能如你所愿。换句话说,put操做将一个元素加入到底层数据结构后,get可能在某段时间内还看不到这个元素,若不考虑内存模型,单从代码逻辑上来看,倒是应该能够看获得的。
下面将结合代码和java内存模型相关内容来分析下put/get方法。put方法咱们只需关注Segment#put,get方法只需关注Segment#get,在继续以前,先要说明一下Segment里有两个volatile变量:count和table;HashEntry里有一个volatile变量:value。
总结
ConcurrentHashMap的弱一致性主要是为了提高效率,是一致性与效率之间的一种权衡。要成为强一致性,就获得处使用锁,甚至是全局锁,这就与Hashtable和同步的HashMap同样了。
为何HashMap是线程不安全的
HashMap 在并发执行 put 操做时会引发死循环,致使 CPU 利用率接近100%。由于多线程会致使 HashMap 的 Node 链表造成环形数据结构,一旦造成环形数据结构,Node 的 next 节点永远不为空,就会在获取 Node 时产生死循环。
如何线程安全的使用HashMap
了解了 HashMap 为何线程不安全,那如今看看如何线程安全的使用 HashMap。这个无非就是如下三种方式:
Hashtable ConcurrentHashMap Synchronized Map
Hashtable
例子
//Hashtable
Map<String, String> hashtable = new Hashtable<>();
//synchronizedMap
Map<String, String> synchronizedHashMap = Collections.synchronizedMap(new HashMap<String, String>());
//ConcurrentHashMap
Map<String, String> concurrentHashMap = new ConcurrentHashMap<>();
Hashtable
先稍微吐槽一下,为啥命名不是 HashTable 啊,看着好难受无论了就装做它叫HashTable 吧。这货已经不经常使用了,就简单说说吧。HashTable 源码中是使用?synchronized?来保证线程安全的,好比下面的 get 方法和 put 方法:
public synchronized V get(Object key) {
// 省略实现
}
public synchronized V put(K key, V value) {
// 省略实现
}
因此当一个线程访问 HashTable 的同步方法时,其余线程若是也要访问同步方法,会被阻塞住。举个例子,当一个线程使用 put 方法时,另外一个线程不但不能够使用 put 方法,连 get 方法都不能够,好霸道啊!!!so~~,效率很低,如今基本不会选择它了。
ConcurrentHashMap
ConcurrentHashMap 于 Java 7 的,和8有区别,在8中 CHM 摒弃了 Segment(锁段)的概念,而是启用了一种全新的方式实现,利用 CAS 算法,有时间会从新总结一下。
SynchronizedMap
synchronizedMap() 方法后会返回一个 SynchronizedMap 类的对象,而在 SynchronizedMap 类中使用了 synchronized 同步关键字来保证对 Map 的操做是线程安全的。
性能对比
这是要靠数听说话的时代,因此不能只靠嘴说 CHM 快,它就快了。写个测试用例,实际的比较一下这三种方式的效率(源码来源),下面的代码分别经过三种方式建立 Map 对象,使用 ExecutorService 来并发运行5个线程,每一个线程添加/获取500K个元素。
Test started for: class java.util.Hashtable
2500K entried added/retrieved in 2018 ms
2500K entried added/retrieved in 1746 ms
2500K entried added/retrieved in 1806 ms
2500K entried added/retrieved in 1801 ms
2500K entried added/retrieved in 1804 ms
For class java.util.Hashtable the average time is 1835 ms
Test started for: class java.util.Collections$SynchronizedMap
2500K entried added/retrieved in 3041 ms
2500K entried added/retrieved in 1690 ms
2500K entried added/retrieved in 1740 ms
2500K entried added/retrieved in 1649 ms
2500K entried added/retrieved in 1696 ms
For class java.util.Collections$SynchronizedMap the average time is 1963 ms
Test started for: class java.util.concurrent.ConcurrentHashMap
2500K entried added/retrieved in 738 ms
2500K entried added/retrieved in 696 ms
2500K entried added/retrieved in 548 ms
2500K entried added/retrieved in 1447 ms
2500K entried added/retrieved in 531 ms
For class java.util.concurrent.ConcurrentHashMap the average time is 792 ms
ConcurrentHashMap 性能是明显优于 Hashtable 和 SynchronizedMap 的,CHM 花费的时间比前两个的一半还少。
多并发状况下HashMap是否还会产生死循环
今天原本想看下了ConcurrentHashMap的源码,ConcurrentHashMap是Java 5中支持高并发、高吞吐量的线程安全HashMap实现。
在看不少博客在介绍ConcurrentHashMap以前,都说HashMap适用于单线程访问,这是由于HashMap的全部方法都没有进行锁同步,所以是线程不安全的,不只如此,当多线程访问的时候还容易产生死循环。
虽然本身在前几天的时候看过HashMap的源码,感受思路啥啥的都还清楚,对于多线程访问只知道HashMap是线程不安全的,可是不知道HashMap在多线程并发的状况下会产生死循环呢,为何会产生,何种状况下才会产生死循环呢???
既然会产生死循环,为何并发状况下,仍是用ConcurrentHashMap。 jdk 好像有,可是Jdk8 已经修复了这个问题。
TreeMap、HashMap、LindedHashMap的区别
LinkedHashMap能够保证HashMap集合有序,存入的顺序和取出的顺序一致。
TreeMap实现SortMap接口,可以把它保存的记录根据键排序,默认是按键值的升序排序,也能够指定排序的比较器,当用Iterator遍历TreeMap时,获得的记录是排过序的。
HashMap不保证顺序,即为无序的,具备很快的访问速度。 HashMap最多只容许一条记录的键为Null;容许多条记录的值为 Null。 HashMap不支持线程的同步。
咱们在开发的过程当中使用HashMap比较多,在Map中在Map 中插入、删除和定位元素,HashMap 是最好的选择。
但若是您要按天然顺序或自定义顺序遍历键,那么TreeMap会更好。
若是须要输出的顺序和输入的相同,那么用LinkedHashMap 能够实现,它还能够按读取顺序来排列。
5七、Map或者HashMap的存储原理
答:HashMap是由数组+链表的一个结构组成,具体参照:HashMap的实现原理
5九、说说常见的集合有哪些吧?
答:Map 接口和 Collection 接口是全部集合框架的父接口:
Collection 接口的子接口包括:Set 接口和 List 接口;
Map 接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap 以及 Properties 等;
Set 接口的实现类主要有:HashSet、TreeSet、LinkedHashSet 等;
List 接口的实现类主要有:ArrayList、LinkedList、Stack 以及 Vector 等。
6二、ConcurrentHashMap 和 Hashtable 的区别? (必问)
答:ConcurrentHashMap 结合了 HashMap 和 HashTable 两者的优点。HashMap 没有考虑同步,hashtable 考虑了同步的问题。可是 hashtable 在每次同步执行时都要锁住整个结构。 ConcurrentHashMap 锁的方式是稍微细粒度的。 ConcurrentHashMap 将 hash 表分为 16 个桶(默认值),诸如 get,put,remove 等经常使用操做只锁当前须要用到的桶。
面试官:ConcurrentHashMap 的具体实现知道吗?
答:
该类包含两个静态内部类 HashEntry 和 Segment;前者用来封装映射表的键值对,后者用来充当锁的角色;
Segment 是一种可重入的锁 ReentrantLock,每一个 Segment 守护一个 HashEntry 数组里得元素,当对 HashEntry 数组的数据进行修改时,必须首先得到对应的 Segment 锁。
6三、HashMap 的长度为何是 2 的幂次方?
答:
经过将 Key 的 hash 值与 length-1 进行 & 运算,实现了当前 Key 的定位,2 的幂次方能够减小冲突(碰撞)的次数,提升 HashMap 查询效率;
若是 length 为 2 的次幂 则 length-1 转化为二进制一定是 11111……的形式,在于 h 的二进制与操做效率会很是的快,并且空间不浪费;
若是 length 不是 2 的次幂,好比 length 为 15,则 length-1 为 14,对应的二进制为 1110,在于 h 与操做,最后一位都为 0,而 0001,0011,0101,1001,1011,0111,1101 这几个位置永远都不能存放元素了,空间浪费至关大。
更糟的是这种状况中,数组能够使用的位置比数组长度小了不少,这意味着进一步增长了碰撞的概率,减慢了查询的效率!这样就会形成空间的浪费。
6五、List、Set 和 Map 的初始容量和加载因子
答:
1. List
ArrayList 的初始容量是 10;加载因子为 0.5; 扩容增量:原容量的 0.5 倍 +1;一次扩容后长度为 16。
Vector 初始容量为 10,加载因子是 1。扩容增量:原容量的 1 倍,如 Vector 的容量为 10,一次扩容后是容量为 20。
2. Set
HashSet,初始容量为 16,加载因子为 0.75; 扩容增量:原容量的 1 倍; 如 HashSet 的容量为 16,一次扩容后容量为 32
3. Map
HashMap,初始容量 16,加载因子为 0.75; 扩容增量:原容量的 1 倍; 如 HashMap 的容量为 16,一次扩容后容量为 32
6六、Comparable 接口和 Comparator 接口有什么区别?
答:
前者简单,可是若是须要从新定义比较类型时,须要修改源代码。
后者不须要修改源代码,自定义一个比较器,实现自定义的比较方法。
6七、Java 集合的快速失败机制 “fail-fast”
答:它是 java 集合的一种错误检测机制,当多个线程对集合进行结构上的改变的操做时,有可能会产生 fail-fast 机制。
例如 :假设存在两个线程(线程 一、线程 2),线程 1 经过 Iterator 在遍历集合 A 中的元素,在某个时候线程 2 修改了集合 A 的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出 ConcurrentModificationException 异常,从而产生 fail-fast 机制。
缘由: 迭代器在遍历时直接访问集合中的内容,而且在遍历过程当中使用一个 modCount 变量。集合在被遍历期间若是内容发生变化,就会改变 modCount 的值。
每当迭代器使用 hashNext()/next() 遍历下一个元素以前,都会检测 modCount 变量是否为 expectedmodCount 值,是的话就返回遍历;不然抛出异常,终止遍历。
解决办法:
在遍历过程当中,全部涉及到改变 modCount 值得地方所有加上 synchronized;
使用 CopyOnWriteArrayList 来替换 ArrayList。
小结:本小节是 Java 中关于集合的考察,是 Java 岗位面试中必考的知识点,除了应该掌握以上的问题,包括各个集合的底层实现也建议各位同窗阅读,加深理解。
一、建立线程的方式及实现:Thread,Runnable,Callable
二、sleep() 、join()、yield()有什么区别
三、说说 CountDownLatch 原理
四、说说 CyclicBarrier 原理
五、说说 Semaphore 原理
六、说说 Exchanger 原理
七、说说 CountDownLatch 与 CyclicBarrier 区别
九、讲讲线程池的实现原理
十、线程池的几种方式
十一、线程的生命周期
十二、
ThreadLocal(线程变量副本)
Synchronized实现内存共享,ThreadLocal为每一个线程维护一个本地变量。
采用空间换时间,它用于线程间的数据隔离,为每个使用该变量的线程提供一个副本,每一个线程均可以独立地改变本身的副本,而不会和其余线程的副本冲突。
ThreadLocal类中维护一个Map,用于存储每个线程的变量副本,Map中元素的键为线程对象,而值为对应线程的变量副本。
ThreadLocal在Spring中发挥着巨大的做用,在管理Request做用域中的Bean、事务管理、任务调度、AOP等模块都出现了它的身影。
Spring中绝大部分Bean均可以声明成Singleton做用域,采用ThreadLocal进行封装,所以有状态的Bean就可以以singleton的方式在多线程中正常工做了。
友情连接:深刻研究java.lang.ThreadLocal类
1四、
fail-fast:机制是java集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操做时,就可能会产生fail-fast事件。
例如:当某一个线程A经过iterator去遍历某集合的过程当中,若该集合的内容被其余线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件
1六、
Volatile和Synchronized四个不一样点:
1 粒度不一样,前者针对变量 ,后者锁对象和类
2 syn阻塞,volatile线程不阻塞
3 syn保证三大特性,volatile不保证原子性
4 syn编译器优化,volatile不优化 volatile具有两种特性:
1.保证此变量对全部线程的可见性,指一条线程修改了这个变量的值,新值对于其余线程来讲是可见的,但并非多线程安全的。
2.禁止指令重排序优化。
Volatile如何保证内存可见性:
1.当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存。
2.当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量。
同步:就是一个任务的完成须要依赖另一个任务,只有等待被依赖的任务完成后,依赖任务才能完成。
异步:不须要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工做,只要本身任务完成了就算完成了,被依赖的任务是否完成会通知回来。(异步的特色就是通知)。 打电话和发短信来比喻同步和异步操做。
阻塞:CPU停下来等一个慢的操做完成之后,才会接着完成其余的工做。
非阻塞:非阻塞就是在这个慢的执行时,CPU去作其余工做,等这个慢的完成后,CPU才会接着完成后续的操做。
非阻塞会形成线程切换增长,增长CPU的使用时间能不能补偿系统的切换成本须要考虑。
友情连接:Java并发编程之volatile关键字解析
1七、
线程池的做用: 在程序启动的时候就建立若干线程来响应处理,它们被称为线程池,里面的线程叫工做线程
第一:下降资源消耗。经过重复利用已建立的线程下降线程建立和销毁形成的消耗。
第二:提升响应速度。当任务到达时,任务能够不须要等到线程建立就能当即执行。
第三:提升线程的可管理性。
经常使用线程池:ExecutorService 是主要的实现类,其中经常使用的有 Executors.newSingleThreadPool(),newFixedThreadPool(),newcachedTheadPool(),newScheduledThreadPool()。
友情连接:线程池原理
友情连接:线程池原理解析
1八、
ExecutorService service = Executors…. ExecutorService service = new ThreadPoolExecutor() ExecutorService service = new ScheduledThreadPoolExecutor();
ThreadPoolExecutor源码分析
线程池自己的状态:
等待任务队列和工做集:
线程池的主要状态锁:
线程池的存活时间和大小:
1.2 ThreadPoolExecutor 的内部工做原理
有了以上定义好的数据,下面来看看内部是如何实现的 。 Doug Lea 的整个思路总结起来就是 5 句话:
若是当前池大小 poolSize 小于 corePoolSize ,则建立新线程执行任务。
若是当前池大小 poolSize 大于 corePoolSize ,且等待队列未满,则进入等待队列
若是当前池大小 poolSize 大于 corePoolSize 且小于 maximumPoolSize ,且等待队列已满,则建立新线程执行任务。
若是当前池大小 poolSize 大于 corePoolSize 且大于 maximumPoolSize ,且等待队列已满,则调用拒绝策略来处理该任务。
线程池里的每一个线程执行完任务后不会马上退出,而是会去检查下等待队列里是否还有线程任务须要执行,若是在 keepAliveTime 里等不到新的任务了,那么线程就会退出。
Executor包结构
CopyOnWriteArrayList : 写时加锁,当添加一个元素的时候,将原来的容器进行copy,复制出一个新的容器,而后在新的容器里面写,写完以后再将原容器的引用指向新的容器,而读的时候是读旧容器的数据,因此能够进行并发的读,但这是一种弱一致性的策略。
使用场景:CopyOnWriteArrayList适合使用在读操做远远大于写操做的场景里,好比缓存。
1九、
wait()和sleep()的区别
sleep来自Thread类,和wait来自Object类
调用sleep()方法的过程当中,线程不会释放对象锁。而 调用 wait 方法线程会释放对象锁
sleep睡眠后不出让系统资源,wait让出系统资源其余线程能够占用CPU
sleep(milliseconds)须要指定一个睡眠时间,时间一到会自动唤醒
2二、wait和sleep的区别,必须理解;
2三、说说阻塞队列的实现:能够参考ArrayBlockingQueue的底层实现(锁和同步都行);
2六、Excutors能够产生哪些线程池;
2八、volatile关键字的用法:使多线程中的变量可见;
2九、多线程
(1)实现线程同步:
http://blog.csdn.net/zhaojw_420/article/details/67823750
(2)生产者消费者问题:
http://blog.csdn.net/zhaojw_420/article/details/67826902
(3)线程安全
(4)线程死锁
(5)Synchronize实现原理
(7)happen-before规则:
http://blog.csdn.net/zhaojw_420/article/details/70477874
(8)线程池
(9)DCL失效缘由以及解决办法:
http://blog.csdn.net/zhaojw_420/article/details/70477921
(10)线程实现方式:Thread,Runable,Callable的区别
3一、synchronized 的实现原理以及锁优化?
3二、volatile 的实现原理?
3五、怎么实现全部线程在等待某个事件的发生才会去执行?:CyclicBarrier
3六、CAS?CAS 有什么缺陷,如何解决?
3七、synchronized 和 lock 有什么区别?
3九、HashMap 的并发问题?
40、ConcurrenHashMap 介绍?1.8 中为何要用红黑树?
4一、AQS
4二、Java 内存模型?
4三、如何保证多线程下 i++ 结果正确?:加锁,或者用AtomicInteger
4四、线程池的种类,区别和使用场景?
4五、分析线程池的实现原理和线程的调度过程?
4六、线程池如何调优,最大数目如何确认?:有个公式
4七、ThreadLocal原理,用的时候须要注意什么?:Thread包含一个Map结构,key就是ThreadLocal变量,value就是ThreadLocal值
4八、CountDownLatch 和 CyclicBarrier 的用法,以及相互之间的差异?:前者是等全部线程完成后另一个线程作一件事情,后者是等全部线程完成后一块儿作一件事情
4九、LockSupport工具
50、Condition接口及其实现原理
5一、Fork/Join框架的理解
5二、分段锁的原理,锁力度减少的思考
5三、八种阻塞队列以及各个阻塞队列的特性
55. 多个线程同时读写,读线程的数量远远⼤于写线程,你认为应该如何解决 并发的问题?你会选择加什么样的锁?:读写锁
56. JAVA的AQS是否了解,它是⼲嘛的?:用来实现加锁的
57. 除了synchronized关键字以外,你是怎么来保障线程安全的?:Lock
58. 何时须要加volatile关键字?它能保证线程安全吗?:须要可见性或者防止重排序的时候,只能保证可见性不能保证线程安全
59. 线程池内的线程若是所有忙,提交⼀个新的任务,会发⽣什么?队列所有 塞满了以后,仍是忙,再提交会发⽣什么?
60. Tomcat自己的参数你⼀般会怎么调整?:调整线程池大小
61. synchronized关键字锁住的是什么东⻄?在字节码中是怎么表示的?在内 存中的对象上表现为何?
62. wait/notify/notifyAll⽅法需不须要被包含在synchronized块中?这是为什 么?:须要,不然会抛出异常
63. ExecutorService你⼀般是怎么⽤的?是每一个service放⼀个仍是⼀个项⽬ ⾥⾯放⼀个?有什么好处?:根据状况来定,看是否须要隔离,仍是须要统一管理
6八、Thread 类中的start() 和 run() 方法有什么区别?
6九、 Java中CyclicBarrier 和 CountDownLatch有什么不一样?
7二、 如何避免死锁?
7三、Java中活锁和死锁有什么区别?
7四、 Java中synchronized 和 ReentrantLock 有什么不一样?
7五、 Java中ConcurrentHashMap的并发度是什么?
7六、 如何在Java中建立Immutable对象?:final,集合类的unmodified。。。
7七、 单例模式的双检锁是什么?
7八、写出3条你遵循的多线程最佳实践:线程池,使用jdk封装的线程安全工具,使用concurrenthashmap代替hashtable
7九、经常使用的线程池模式以及不一样线程池的使用场景
81. wait和sleep的区别
一、sleep()方法是属于Thread类中的,而wait()方法,则是属于Object类中的。
二、sleep()方法致使了程序暂停执行指定的时间,让出cpu给其余线程,可是他的监控状态依然保持着,当指定的时间到了又会自动恢复运行状态。因此在调用sleep()方法的过程当中,线程不会释放对象锁。
三、调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
8三、多线程实现方式:http://www.javashuo.com/article/p-uawdyimt-ce.html
8四、线程的状态转换:http://blog.csdn.net/sinat_36042530/article/details/52565296
8五、如何中止一个线程:http://www.javashuo.com/article/p-zntbvsla-ct.html
8六、什么是线程安全:http://blog.csdn.net/ghevinn/article/details/37764791
8七、synchronized和lock的区别:http://blog.csdn.net/u012403290/article/details/64910926?locationNum=11&fps=1
8九、.java线程池:http://www.importnew.com/19011.html
90、.并发工具类:http://blog.csdn.net/sunxianghuang/article/details/52277394
9一、.并发容器类:http://blog.csdn.net/jianghuxiaojin/article/details/52006183
9三、Volatile的特征:
A、禁止指令重排(有例外)
B、可见性
Volatile的内存语义:
当写一个volatile变量时,JMM会把线程对应的本地内存中的共享变量值刷新到主内存。
当读一个volatile变量时,JMM会把线程对应的本地内存置为无效,线程接下来将从主内存中读取共享变量。
Volatile的重排序
一、当第二个操做为volatile写操作时,无论第一个操做是什么(普通读写或者volatile读写),都不能进行重排序。这个规则确保volatile写以前的全部操做都不会被重排序到volatile以后;
二、当第一个操做为volatile读操做时,无论第二个操做是什么,都不能进行重排序。这个规则确保volatile读以后的全部操做都不会被重排序到volatile以前;
三、当第一个操做是volatile写操做时,第二个操做是volatile读操做,不能进行重排序。
这个规则和前面两个规则一块儿构成了:两个volatile变量操做不可以进行重排序;
除以上三种状况之外能够进行重排序。
好比:
一、第一个操做是普通变量读/写,第二个是volatile变量的读;
二、第一个操做是volatile变量的写,第二个是普通变量的读/写;
9四、内存屏障/内存栅栏
内存屏障(Memory Barrier,或有时叫作内存栅栏,Memory Fence)是一种CPU指令,用于控制特定条件下的重排序和内存可见性问题。Java编译器也会根据内存屏障的规则禁止重排序。(也就是让一个CPU处理单元中的内存状态对其它处理单元可见的一项技术。)
内存屏障能够被分为如下几种类型:
LoadLoad屏障:对于这样的语句Load1; LoadLoad; Load2,在Load2及后续读取操做要读取的数据被访问前,保证Load1要读取的数据被读取完毕。
StoreStore屏障:对于这样的语句Store1; StoreStore; Store2,在Store2及后续写入操做执行前,保证Store1的写入操做对其它处理器可见。
LoadStore屏障:对于这样的语句Load1; LoadStore; Store2,在Store2及后续写入操做被刷出前,保证Load1要读取的数据被读取完毕。
StoreLoad屏障:对于这样的语句Store1; StoreLoad; Load2,在Load2及后续全部读取操做执行前,保证Store1的写入对全部处理器可见。它的开销是四种屏障中最大的。
在大多数处理器的实现中,这个屏障是个万能屏障,兼具其它三种内存屏障的功能。
内存屏障阻碍了CPU采用优化技术来下降内存操做延迟,必须考虑所以带来的性能损失。为了达到最佳性能,最好是把要解决的问题模块化,这样处理器能够按单元执行任务,而后在任务单元的边界放上全部须要的内存屏障。采用这个方法可让处理器不受限的执行一个任务单元。合理的内存屏障组合还有一个好处是:缓冲区在第一次被刷后开销会减小,由于再填充改缓冲区不须要额外工做了。
9五、happens-before原则
9六、
Java 线程有哪些状态,这些状态之间是如何转化的?
新建(new):新建立了一个线程对象。
可运行(runnable):线程对象建立后,其余线程(好比main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。
运行(running):可运行状态(runnable)的线程得到了cpu 时间片(timeslice) ,执行程序代码。
阻塞(block):阻塞状态是指线程由于某种缘由放弃了cpu 使用权,也即让出了cpu timeslice,暂时中止运行。直到线程进入可运行(runnable)状态,才有机会再次得到cpu timeslice 转到运行(running)状态。阻塞的状况分三种:
(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
(三). 其余阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程从新转入可运行(runnable)状态。
死亡(dead):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
9七、
Java中CAS算法
参考:http://www.kancloud.cn/seaboat/java-concurrent/117870
9八、
Java线程间的通讯方式?
参考1:http://www.cnblogs.com/mengdd/archive/2013/02/20/2917956.html
参考2:http://www.jb51.net/article/84213.htm
100、Callable和Future的了解。
10一、线程池的参数有哪些,在线程池建立一个线程的过程。
10四、Lock接口有哪些实现类,使用场景是什么。
10五、可重入锁的用处及实现原理,写时复制的过程,读写锁,分段锁(ConcurrentHashMap中的segment)。
10六、悲观锁,乐观锁,优缺点,CAS有什么缺陷,该如何解决。
10七、ABC三个线程如何保证顺序执行。:先标序号,循环检测并wait,到序号了则执行
112.多线程的实现方式#
继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。
11三、.线程的状态转换#
11四、.如何中止一个线程#
参考文章:
http://www.cnblogs.com/greta/p/5624839.html
11五、.什么是线程安全#
线程安全就是多线程访问同一代码,不会产生不肯定的结果。
11六、.如何保证线程安全#
对非安全的代码进行加锁控制;
使用线程安全的类;
多线程并发状况下,线程共享的变量改成方法级的局部变量。
11八、.synchronized和Lock的区别#
主要相同点:Lock能完成synchronized所实现的全部功能
主要不一样点:Lock有比synchronized更精确的线程语义和更好的性能。Lock的锁定是经过代码实现的,而synchronized是在JVM层面上实现的,synchronized会自动释放锁,而Lock必定要求程序员手工释放,而且必须在finally从句中释放。Lock还有更强大的功能,例如,它的tryLock方法能够非阻塞方式去拿锁。Lock锁的范围有局限性,块范围,而synchronized能够锁住块、对象、类。
11九、.多线程如何进行信息交互#
void notify() 唤醒在此对象监视器上等待的单个线程。
void notifyAll() 唤醒在此对象监视器上等待的全部线程。
void wait() 致使当前的线程等待,直到其余线程调用此对象的notify()方法或notifyAll()方法。
void wait(long timeout) 致使当前的线程等待,直到其余线程调用此对象的notify()方法或notifyAll()方法,或者超过指定的时间量。
void wait(long timeout, int nanos) 致使当前的线程等待,直到其余线程调用此对象的notify()方法或notifyAll()方法,或者其余某个线程中断当前线程,或者已超过某个实际时间量。
120、.sleep和wait的区别(考察的方向是是否会释放锁)#
sleep()方法是Thread类中方法,而wait()方法是Object类中的方法。
sleep()方法致使了程序暂停执行指定的时间,让出cpu该其余线程,可是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态,在调用sleep()方法的过程当中,线程不会释放对象锁。而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备。
12五、.Java线程池技术及原理#
参考文章:
http://www.importnew.com/19011.html
http://www.cnblogs.com/dolphin0520/p/3932921.html
12六、.java并发包concurrent及经常使用的类#
这个内容有点多,参考文章:
并发包诸类概览:http://www.raychase.net/1912
线程池:http://www.cnblogs.com/dolphin0520/p/3932921.html
锁:http://www.cnblogs.com/dolphin0520/p/3923167.html
集合:http://www.cnblogs.com/huangfox/archive/2012/08/16/2642666.html
12七、.volatile关键字#
用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值。volatile很容易被误用,用来进行原子性操做。
Java语言中的volatile变量能够被看做是一种“程度较轻的
synchronized”;与
synchronized 块相比,volatile 变量所需的编码较少,而且运行时开销也较少,可是它所能实现的功能也仅是synchronized的一部分。锁提供了两种主要特性:互斥(mutual
exclusion)和可见性(visibility)。互斥即一次只容许一个线程持有某个特定的锁,所以可以使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程可以使用该共享数据。可见性必须确保释放锁以前对共享数据作出的更改对于随后得到该锁的另外一个线程是可见的,若是没有同步机制提供的这种可见性保证,线程看到的共享变量多是修改前的值或不一致的值,这将引起许多严重问题。Volatile变量具备synchronized的可见性特性,可是不具有原子特性。这就是说线程可以自动发现volatile
变量的最新值。
要使volatile变量提供理想的线程安全,必须同时知足下面两个条件:对变量的写操做不依赖于当前值;该变量没有包含在具备其余变量的不变式中。
第一个条件的限制使volatile变量不能用做线程安全计数器。虽然增量操做(x++)看上去相似一个单独操做,实际上它是一个由读取-修改-写入操做序列组成的组合操做,必须以原子方式执行,而volatile不能提供必须的原子特性。实现正确的操做须要使x 的值在操做期间保持不变,而volatile
变量没法实现这点。
每个线程运行时都有一个线程栈,线程栈保存了线程运行时候变量值信息。当线程访问某一个对象时候值的时候,首先经过对象的引用找到对应在堆内存的变量的值,而后把堆内存变量的具体值load到线程本地内存中,创建一个变量副本,以后线程就再也不和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,在修改完以后的某一个时刻(线程退出以前),自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。
read and load 从主存复制变量到当前工做内存
use and assign 执行代码,改变共享变量值
store and write 用工做内存数据刷新主存相关内容
其中use and
assign 能够屡次出现,可是这一些操做并非原子性,也就是在read load以后,若是主内存count变量发生修改以后,线程工做内存中的值因为已经加载,不会产生对应的变化,因此计算出来的结果会和预期不同。
解答:线程原理及实现
130、另总结多线程相关面试题50道
13二、方法内部,如何实现更好的异步?
答:咱们知道异步其实就是让另外一个线程去跑,那么如何建立线程? 第一种直接new Thread ,第二种new 一个实现Runnable接口的实现类。 第三种,经过线程池来管理建立等 ,这里说到更好的实现异步,那就是说咱们在方法内部避免频繁的new 线程,就能够考虑线程池了。 那么线程池如何建立? 这里能够new 一个线程池,可是须要考虑单例,或者在程序初始启东时,就建立一个线程池,让他跑着,而后在具体方法的时候,经过线程池来建立线程,实现异步
13三、多线程和单线程的区别和联系:
答:
在单核 CPU 中,将 CPU 分为很小的时间片,在每一时刻只能有一个线程在执行,是一种微观上轮流占用 CPU 的机制。
多线程会存在线程上下文切换,会致使程序执行速度变慢,即采用一个拥有两个线程的进程执行所须要的时间比一个线程的进程执行两次所须要的时间要多一些。
结论:即采用多线程不会提升程序的执行速度,反而会下降速度,可是对于用户来讲,能够减小用户的响应时间。
13四、如何指定多个线程的执行顺序?
解析:面试官会给你举个例子,如何让 10 个线程按照顺序打印 0123456789?(写代码实现)
答:
设定一个 orderNum,每一个线程执行结束以后,更新 orderNum,指明下一个要执行的线程。而且唤醒全部的等待线程。
在每个线程的开始,要 while 判断 orderNum 是否等于本身的要求值!!不是,则 wait,是则执行本线程。
13六、多线程产生死锁的 4 个必要条件?
答:
互斥条件:一个资源每次只能被一个线程使用;
请求与保持条件:一个线程因请求资源而阻塞时,对已得到的资源保持不放;
不剥夺条件:进程已经得到的资源,在未使用完以前,不能强行剥夺;
循环等待条件:若干线程之间造成一种头尾相接的循环等待资源关系。
面试官:如何避免死锁?(常常接着问这个问题哦~)
答:指定获取锁的顺序,举例以下:
好比某个线程只有得到 A 锁和 B 锁才能对某资源进行操做,在多线程条件下,如何避免死锁?
得到锁的顺序是必定的,好比规定,只有得到 A 锁的线程才有资格获取 B 锁,按顺序获取锁就能够避免死锁!!!
13七、sleep( ) 和 wait( n)、wait( ) 的区别:
答:
sleep 方法:是 Thread 类的静态方法,当前线程将睡眠 n 毫秒,线程进入阻塞状态。当睡眠时间到了,会解除阻塞,进行可运行状态,等待 CPU 的到来。睡眠不释放锁(若是有的话);
wait 方法:是 Object 的方法,必须与 synchronized 关键字一块儿使用,线程进入阻塞状态,当 notify 或者 notifyall 被调用后,会解除阻塞。可是,只有从新占用互斥锁以后才会进入可运行状态。睡眠时,释放互斥锁。
13八、synchronized 关键字:
答:底层实现:
进入时,执行 monitorenter,将计数器 +1,释放锁 monitorexit 时,计数器-1;
当一个线程判断到计数器为 0 时,则当前锁空闲,能够占用;反之,当前线程进入等待状态。
含义:(monitor 机制)
Synchronized 是在加锁,加对象锁。对象锁是一种重量锁(monitor),synchronized 的锁机制会根据线程竞争状况在运行时会有偏向锁(单一线程)、轻量锁(多个线程访问 synchronized 区域)、对象锁(重量锁,多个线程存在竞争的状况)、自旋锁等。
该关键字是一个几种锁的封装。
13九、volatile 关键字
答:该关键字能够保证可见性不保证原子性。
功能:
主内存和工做内存,直接与主内存产生交互,进行读写操做,保证可见性;
禁止 JVM 进行的指令重排序。
解析:关于指令重排序的问题,能够查阅 DCL 双检锁失效相关资料。
锁机制
一、说说线程安全问题
二、volatile 实现原理
三、synchronize 实现原理
四、synchronized 与 lock 的区别
五、CAS 乐观锁
六、ABA 问题
七、乐观锁的业务场景及实现方式
八、
Synchronized 与Lock都是可重入锁,同一个线程再次进入同步代码的时候.能够使用本身已经获取到的锁。
Synchronized是悲观锁机制,独占锁。而Locks.ReentrantLock是,每次不加锁而是假设没有冲突而去完成某项操做,若是由于冲突失败就重试,直到成功为止。 ReentrantLock适用场景
某个线程在等待一个锁的控制权的这段时间须要中断
须要分开处理一些wait-notify,ReentrantLock里面的Condition应用,可以控制notify哪一个线程,锁能够绑定多个条件。
具备公平锁功能,每一个到来的线程都将排队等候。
友情连接: Synchronized关键字、Lock,并解释它们之间的区别
九、
CAS(Compare And Swap) 无锁算法: CAS是乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知此次竞争中失败,并能够再次尝试。CAS有3个操做数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改成B,不然什么都不作。
友情连接:非阻塞同步算法与CAS(Compare and Swap)无锁算法
1三、悲观锁和乐观锁的区别,怎么实现
悲观锁:一段执行逻辑加上悲观锁,不一样线程同时执行时,只能有一个线程执行,其余的线程在入口处等待,直到锁被释放。
乐观锁:一段执行逻辑加上乐观锁,不一样线程同时执行时,能够同时进入执行,在最后更新数据的时候要检查这些数据是否被其余线程修改了(版本和执行初是否相同),没有修改则进行更新,不然放弃本次操做。
悲观锁的实现:
1
2
3
4
5
6
7
8
9
10
|
//0.开始事务
begin ;/ begin work ;/start transaction ; (三者选一就能够)
//1.查询出商品信息
select status from t_goods where id=1 for update ;
//2.根据商品信息生成订单
insert into t_orders (id,goods_id) values ( null ,1);
//3.修改商品status为2
update t_goods set status=2;
//4.提交事务
commit ;/ commit work ;
|
乐观锁的实现:
1
2
3
4
5
6
7
|
1.查询出商品信息
select (status,status,version) from t_goods where id=#{id}
2.根据商品信息生成订单
3.修改商品status为2
update t_goods
set status=2,version=version+1
where id=#{id} and version=#{version};
|
JVM
一、
Java内存模型:
Java虚拟机规范中将Java运行时数据分为六种。
1.程序计数器:是一个数据结构,用于保存当前正常执行的程序的内存地址。Java虚拟机的多线程就是经过线程轮流切换并分配处理器时间来实现的,为了线程切换后能恢复到正确的位置,每条线程都须要一个独立的程序计数器,互不影响,该区域为“线程私有”。
2.Java虚拟机栈:线程私有的,与线程生命周期相同,用于存储局部变量表,操做栈,方法返回值。局部变量表放着基本数据类型,还有对象的引用。
3.本地方法栈:跟虚拟机栈很像,不过它是为虚拟机使用到的Native方法服务。
4.Java堆:全部线程共享的一块内存区域,对象实例几乎都在这分配内存。
5.方法区:各个线程共享的区域,储存虚拟机加载的类信息,常量,静态变量,编译后的代码。
6.运行时常量池:表明运行时每一个class文件中的常量表。包括几种常量:编译时的数字常量、方法或者域的引用。
友情连接: Java中JVM虚拟机详解
二、
“你能不能谈谈,java GC是在何时,对什么东西,作了什么事情?”
在何时:
1.新生代有一个Eden区和两个survivor区,首先将对象放入Eden区,若是空间不足就向其中的一个survivor区上放,若是仍然放不下就会引起一次发生在新生代的minor GC,将存活的对象放入另外一个survivor区中,而后清空Eden和以前的那个survivor区的内存。在某次GC过程当中,若是发现仍然又放不下的对象,就将这些对象放入老年代内存里去。
2.大对象以及长期存活的对象直接进入老年区。
3.当每次执行minor GC的时候应该对要晋升到老年代的对象进行分析,若是这些立刻要到老年区的老年对象的大小超过了老年区的剩余大小,那么执行一次Full GC以尽量地得到老年区的空间。
对什么东西:从GC Roots搜索不到,并且通过一次标记清理以后仍没有复活的对象。
作什么: 新生代:复制清理; 老年代:标记-清除和标记-压缩算法; 永久代:存放Java中的类和加载类的类加载器自己。
GC Roots都有哪些: 1. 虚拟机栈中的引用的对象 2. 方法区中静态属性引用的对象,常量引用的对象 3. 本地方法栈中JNI(即通常说的Native方法)引用的对象。
友情连接:Java GC的那些事(上)
友情连接:Java GC的那些事(下)
友情连接:CMS垃圾收集器介绍
三、
类加载器工做机制:
1.装载:将Java二进制代码导入jvm中,生成Class文件。
2.链接:a)校验:检查载入Class文件数据的正确性 b)准备:给类的静态变量分配存储空间 c)解析:将符号引用转成直接引用
3:初始化:对类的静态变量,静态方法和静态代码块执行初始化工做。
双亲委派模型:类加载器收到类加载请求,首先将请求委派给父类加载器完成 用户自定义加载器->应用程序加载器->扩展类加载器->启动类加载器。
友情连接:深刻理解Java虚拟机笔记—双亲委派模型
友情连接:JVM类加载的那些事
友情连接:JVM(1):Java 类的加载机制
四、
Java的四种引用,强弱软虚,以及用到的场景
a.强引用:若是一个对象具备强引用,它就不会被垃圾回收器回收。即便当前内存空间不足,JVM也不会回收它,而是抛出 OutOfMemoryError 错误,使程序异常终止。若是想中断强引用和某个对象之间的关联,能够显式地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象。
b.软引用:在使用软引用时,若是内存的空间足够,软引用就能继续被使用,而不会被垃圾回收器回收,只有在内存不足时,软引用才会被垃圾回收器回收。
c.弱引用:具备弱引用的对象拥有的生命周期更短暂。由于当 JVM 进行垃圾回收,一旦发现弱引用对象,不管当前内存空间是否充足,都会将弱引用回收。不过因为垃圾回收器是一个优先级较低的线程,因此并不必定能迅速发现弱引用对象。
d.虚引用:顾名思义,就是形同虚设,若是一个对象仅持有虚引用,那么它至关于没有引用,在任什么时候候均可能被垃圾回收器回收。
五、
JAVA 中堆和栈的区别,说下java 的内存机制
a.基本数据类型比变量和对象的引用都是在栈分配的
b.堆内存用来存放由new建立的对象和数组
c.类变量(static修饰的变量),程序在一加载的时候就在堆中为类变量分配内存,堆中的内存地址存放在栈中
d.实例变量:当你使用java关键字new的时候,系统在堆中开辟并不必定是连续的空间分配给变量,是根据零散的堆内存地址,经过哈希算法换算为一长串数字以表征这个变量在堆中的”物理位置”,实例变量的生命周期–当实例变量的引用丢失后,将被GC(垃圾回收器)列入可回收“名单”中,但并非立刻就释放堆中内存
e.局部变量: 由声明在某方法,或某代码段里(好比for循环),执行到它的时候在栈中开辟内存,当局部变量一但脱离做用域,内存当即释放
六、JAVA多态的实现原理
a.抽象的来说,多态的意思就是同一消息能够根据发送对象的不一样而采用多种不一样的行为方式。(发送消息就是函数调用)
b.实现的原理是动态绑定,程序调用的方法在运行期才动态绑定,追溯源码能够发现,JVM 经过参数的自动转型来找到合适的办法。
七、JVM的内存结构,JVM的算法;
九、数组在内存中如何分配:基本类型数组在栈上分配,对象类型在堆上分配
七、java中常说的堆和栈,分别是什么数据结构;另外,为何要分为堆和栈来存储数据。
八、Java虚拟机
(1)组成以及各部分做用:
http://blog.csdn.net/zhaojw_420/article/details/70477953
(2)类加载器——ClassLoader:
http://blog.csdn.net/zhaojw_420/article/details/53373898
(3)类加载器的父亲委托机制深度详解:
http://blog.csdn.net/zhaojw_420/article/details/53284225
(4)JVM调优:
http://blog.csdn.net/zhaojw_420/article/details/70527138
(5)垃圾回收:
http://blog.csdn.net/zhaojw_420/article/details/70527232
九、Java内存模型
http://blog.csdn.net/zhaojw_420/article/details/70477903
十二、讲讲什么状况下回出现内存溢出,内存泄漏?
1三、说说Java线程栈
1四、JVM 年轻代到年老代的晋升过程的判断条件是什么呢?
1五、JVM 出现 fullGC 很频繁,怎么去线上排查问题?
1六、类加载为何要使用双亲委派模式,有没有什么场景是打破了这个模式?
1七、类的实例化顺序:先父类,再子类
1八、JVM垃圾回收机制,什么时候触发MinorGC等操做:eden区没法为对象分配空间
1九、JVM 中一次完整的 GC 流程(从 ygc 到 fgc)是怎样的
20、各类回收器,各自优缺点,重点CMS、G1
2一、各类回收算法
2二、OOM错误,stackoverflow错误,permgen space错误
2三、Java中有哪些多线程同步的手段
这个问题也能够延伸出不少知识,synchronized
的实现原理、synchronized
中的锁膨胀、为何有时候使用volatile
能够带来更好的性能、悲观锁&乐观锁的概念、新一代的基于Lock
的锁机制,更甚者可能会问到Java的内存模型(JMM)。
24. 你知道哪些或者大家线上使⽤什么GC策略? 它有什么优点,适⽤于什么 场景?
25. JAVA类加载器包括⼏种?它们之间的⽗⼦关系是怎么样的?双亲委派机 制是什么意思?有什么好处?
26. 如何⾃定义⼀个类加载器?你使⽤过哪些或者你在什么场景下须要⼀个⾃ 定义的类加载器吗?
27. 堆内存设置的参数是什么? 5. Perm Space中保存什么数据? 会引发OutOfMemory吗? 6. 作gc时,⼀个对象在内存各个Space中被移动的顺序是什么?
28. 你有没有遇到过OutOfMemory问题?你是怎么来处理这个问题的?处理过程当中有哪些收获?
29. 1.8以后Perm Space有哪些变更? MetaSpace⼤⼩默认是⽆限的么? 仍是大家会经过什么⽅式来指定⼤⼩?:不是,默认20M,XX:MetaspaceSize=200m;-XX:MaxMetaspaceSize=256m
30. Jstack是⼲什么的? Jstat呢? 若是线上程序周期性地出现卡顿,你怀疑多是gc致使的,你会怎么来排查这个问题?线程⽇志⼀般你会看其中的什么 部分?:jstack查看线程堆栈|查看fullgc/minor时间和频率|线程日志通常看blocked-->waiting-->timed_waiting
31. StackOverFlow异常有没有遇到过?⼀般你猜想会在什么状况下被触发?如何指定⼀个线程的堆栈⼤⼩?⼀般大家写多少?:xss来指定
32. JVM的内存结构
根据 JVM 规范,JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分。
一、Java虚拟机栈:
线程私有;每一个方法在执行的时候会建立一个栈帧,存储了局部变量表,操做数栈,动态链接,方法返回地址等;每一个方法从调用到执行完毕,对应一个栈帧在虚拟机栈中的入栈和出栈。
二、堆:
线程共享;被全部线程共享的一块内存区域,在虚拟机启动时建立,用于存放对象实例。
三、方法区:
线程共享;被全部线程共享的一块内存区域;用于存储已被虚拟机加载的类信息,常量,静态变量等。
四、程序计数器:
线程私有;是当前线程所执行的字节码的行号指示器,每条线程都要有一个独立的程序计数器,这类内存也称为“线程私有”的内存。
五、本地方法栈:
线程私有;主要为虚拟机使用到的Native方法服务。
3四、 数组在内存中如何分配
一、简单的值类型的数组,每一个数组成员是一个引用(指针),引用到栈上的空间(由于值类型变量的内存分配在栈上)
二、引用类型,类类型的数组,每一个数组成员还是一个引用(指针),引用到堆上的空间(由于类的实例的内存分配在堆上)
3五、请写一段栈溢出、堆溢出的代码
递归调用能够致使栈溢出
不断建立对象能够致使堆溢出
3六、java中常说的堆和栈,分别是什么数据结构;另外,为何要分为堆和栈来存储数据
为何要划分堆和栈
一、从软件设计的角度看,栈表明了处理逻辑,而堆表明了数据。这样分开,使得处理逻辑更为清晰。
二、堆与栈的分离,使得堆中的内容能够被多个栈共享。一方面这种共享提供了一种有效的数据交互方式(如:共享内存),另外一方面,堆中的共享常量和缓存能够被全部栈访问,节省了空间。
三、栈由于运行时的须要,好比保存系统运行的上下文,须要进行地址段的划分。因为栈只能向上增加,所以就会限制住栈存储内容的能力。而堆不一样,堆中的对象是能够根据须要动态增加的,所以栈和堆的拆分,使得动态增加成为可能,相应栈中只需记录堆中的一个地址便可。
四、体现了Java面向对象这一核心特色(也能够继续说一些本身的理解)
3七、.Jvm垃圾收集器与内存分配策略:http://www.importnew.com/23035.html
3八、.Jvm运行和类加载过程:http://www.javashuo.com/article/p-updqgwok-dd.html
3九、.Jvm字节码执行:http://blog.csdn.net/u012077981/article/details/40156391
40、.java内存模型:http://blog.csdn.net/suifeng3051/article/details/52611310;
http://www.hao124.net/article/49
4一、
Java8的内存分代改进
参考:http://blog.csdn.net/chlu113/article/details/51890469
4二、对Java内存模型的理解以及其在并发当中的做用?
参考:http://www.cnblogs.com/_popc/p/6096517.html
4三、Java中堆内存和栈内存区别?
参考:http://www.cnblogs.com/whgw/archive/2011/09/29/2194997.html
4四、JVM的内存结构。
4五、JVM方法栈的工做过程,方法栈和本地方法栈有什么区别。
4六、JVM的栈中引用如何和堆中的对象产生关联。
4七、能够了解一下逃逸分析技术。
4八、GC的常见算法,CMS以及G1的垃圾回收过程,CMS的各个阶段哪两个是Stop the world的,CMS会不会产生碎片,G1的优点。
4九、标记清除和标记整理算法的理解以及优缺点。
50、eden survivor区的比例,为何是这个比例,eden survivor的工做过程。
5一、JVM如何判断一个对象是否该被GC,能够视为root的都有哪几种类型。
5二、强软弱虚引用的区别以及GC对他们执行怎样的操做。
5三、Java是否能够GC直接内存。
5四、Java类加载的过程。
5五、双亲委派模型的过程以及优点。
5六、经常使用的JVM调优参数。
5七、dump文件的分析。
5八、Java有没有主动触发GC的方式(没有)。
5九、内存溢出和内存泄漏的区别#
内存溢出是指程序在申请内存时,没有足够的内存空间供其使用,出现out of
memory。
内存泄漏是指分配出去的内存再也不使用,可是没法回收。
60、Java内存模型及各个区域的OOM,如何重现OOM#
这部份内容很重要,详细阅读《深刻理解Java虚拟机》,也能够详细阅读这篇文章http://hllvm.group.iteye.com/group/wiki/2857-JVM
6一、出现OOM如何解决#
一. 可经过命令按期抓取heap dump或者启动参数OOM时自动抓取heap dump文件。
二. 经过对比多个heap dump,以及heap dump的内容,分析代码找出内存占用最多的地方。
三. 分析占用的内存对象,是不是由于错误致使的内存未及时释放,或者数据过多致使的内存溢出。
6三、Java内存管理及回收算法#
阅读这篇文章:http://www.cnblogs.com/hnrainll/archive/2013/11/06/3410042.html
6四、Java类加载器及如何加载类(双亲委派)#
阅读文章:
https://www.ibm.com/developerworks/cn/java/j-lo-classloader/(推荐)
http://blog.csdn.net/zhoudaxia/article/details/35824249
6五、 JVM结构原理、GC工做机制详解
答:具体参照:JVM结构、GC工做机制详解 ,说到GC,记住两点:一、GC是负责回收全部无任何引用对象的内存空间。 注意:垃圾回收回收的是无任何引用的对象占据的内存空间而不是对象自己,二、GC回收机制的两种算法,a、引用计数法 b、可达性分析算法( 这里的可达性,你们能够看基础2 Java对象的什么周期),至于更详细的GC算法介绍,你们能够参考:Java GC机制算法
6六、谈谈你对JVM的理解?
答: Java语言的一个很是重要的特色就是与平台的无关性。而使用Java虚拟机是实现这一特色的关键。Java编译器只要面向JVM,生成JVM能理解的代码或字节码文件。Java源文件经编译成字节码程序,经过JVM将每一条指令翻译成不一样平台机器码,经过特定平台运行。
JVM执行程序的过程 :I.加载。class文件 ,II.管理并分配内存 ,III.执行垃圾收集
JRE(java运行时环境)由JVM构造的java程序的运行环境
具体详情:JVM原理和调优
既然是 Java 开发面试,那么对 JVM 的考察固然也是必须的,面试官通常会问你对 JVM 有了解吗?
我一般都会把我所了解的都说一遍,包括:JVM 内存划分、JVM 垃圾回收的含义,有哪些 GC 算法,年轻代和老年代各自的特色通通阐述一遍。
6七、JVM 内存划分:
方法区(线程共享):常量、静态变量、JIT(即时编译器) 编译后的代码也都在方法区;
堆内存(线程共享):垃圾回收的主要场所;
程序计数器: 当前线程执行的字节码的位置指示器;
虚拟机栈(栈内存):保存局部变量、基本数据类型变量以及堆内存中某个对象的引用变量;
本地方法栈 :为 JVM 提供使用 native 方法的服务。
6八、相似-Xms、-Xmn 这些参数的含义:
答:
堆内存分配:
JVM 初始分配的内存由-Xms 指定,默认是物理内存的 1/64;
JVM 最大分配的内存由-Xmx 指定,默认是物理内存的 1/4;
默认空余堆内存小于 40% 时,JVM 就会增大堆直到-Xmx 的最大限制;空余堆内存大于 70% 时,JVM 会减小堆直到 -Xms 的最小限制;
所以服务器通常设置-Xms、-Xmx 相等以免在每次 GC 后调整堆的大小。对象的堆内存由称为垃圾回收器的自动内存管理系统回收。
非堆内存分配:
JVM 使用-XX:PermSize 设置非堆内存初始值,默认是物理内存的 1/64;
由 XX:MaxPermSize 设置最大非堆内存的大小,默认是物理内存的 1/4;
-Xmn2G:设置年轻代大小为 2G;
-XX:SurvivorRatio,设置年轻代中 Eden 区与 Survivor 区的比值。
6九、垃圾回收算法有哪些?
答:
引用计数 :原理是此对象有一个引用,即增长一个计数,删除一个引用则减小一个计数。垃圾回收时,只用收集计数为 0 的对象。此算法最致命的是没法处理循环引用的问题;
标记-清除 :此算法执行分两阶段。第一阶段从引用根节点开始标记全部被引用的对象,第二阶段遍历整个堆,把未标记的对象清除;
此算法须要暂停整个应用,同时,会产生内存碎片;
复制算法 :此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另一个区域中;
此算法每次只处理正在使用中的对象,所以复制成本比较小,同时复制过去之后还能进行相应的内存整理,不会出现 “碎片” 问题。固然,此算法的缺点也是很明显的,就是须要两倍内存空间;
标记-整理 :此算法结合了 “标记-清除” 和 “复制” 两个算法的优势。也是分两阶段,第一阶段从根节点开始标记全部被引用对象,第二阶段遍历整个堆,把清除未标记对象而且把存活对象 “压缩” 到堆的其中一块,按顺序排放。
此算法避免了 “标记-清除” 的碎片问题,同时也避免了 “复制” 算法的空间问题。
70、root 搜索算法中,哪些能够做为 root?
答:
被启动类(bootstrap 加载器)加载的类和建立的对象;
JavaStack 中的引用的对象 (栈内存中引用的对象);
方法区中静态引用指向的对象;
方法区中常量引用指向的对象;
Native 方法中 JNI 引用的对象。
7一、GC 何时开始?
答:GC 常常发生的区域是堆区,堆区还能够细分为新生代、老年代,新生代还分为一个 Eden 区和两个 Survivor 区。
对象优先在 Eden 中分配,当 Eden 中没有足够空间时,虚拟机将发生一次 Minor GC,由于 Java 大多数对象都是朝生夕灭,因此 Minor GC 很是频繁,并且速度也很快;
Full GC,发生在老年代的 GC,当老年代没有足够的空间时即发生 Full GC,发生 Full GC 通常都会有一次 Minor GC。
大对象直接进入老年代,如很长的字符串数组,虚拟机提供一个;XX:PretenureSizeThreadhold 参数,令大于这个参数值的对象直接在老年代中分配,避免在 Eden 区和两个 Survivor 区发生大量的内存拷贝;
发生 Minor GC 时,虚拟机会检测以前每次晋升到老年代的平均大小是否大于老年代的剩余空间大小,若是大于,则进行一次 Full GC,若是小于,则查看 HandlePromotionFailure 设置是否容许担保失败,若是容许,那只会进行一次 Minor GC,若是不容许,则改成进行一次 Full GC。
7二、内存泄漏和内存溢出
答:
概念:
内存溢出指的是内存不够用了;
内存泄漏是指对象可达,可是没用了。即本该被 GC 回收的对象并无被回收;
内存泄露是致使内存溢出的缘由之一;内存泄露积累起来将致使内存溢出。
内存泄漏的缘由分析:
长生命周期的对象引用短生命周期的对象;
没有将无用对象置为 null。
小结:本小节涉及到 JVM 虚拟机,包括对内存的管理等知识,相对较深。除了以上问题,面试官会继续问你一些比较深的问题,可能也是为了看看你的极限在哪里吧。
好比:内存调优、内存管理,是否遇到过内存泄漏的实际案例、是否真正关心过内存等。因为本人实际项目经验不足,这些深层次问题并无接触过,各位有须要能够上网查阅。
IO/NIO
一、bio,nio,aio的区别;
二、nio框架:dubbo的实现原理;
三、京东内部的jsf是使用的什么协议通信:可参见dubbo的协议;
五、http://blog.csdn.net/zhaojw_420/article/details/70526695
六、BIO、NIO和AIO的区别
Java BIO : 同步并阻塞,服务器实现模式为一个链接一个线程,即客户端有链接请求时服务器端就须要启动一个线程进行处理,若是这个链接不作任何事情会形成没必要要的线程开销,固然能够经过线程池机制改善。
Java NIO : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的链接请求都会注册到多路复用器上,多路复用器轮询到链接有I/O请求时才启动一个线程进行处理。
Java AIO: 异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。
NIO比BIO的改善之处是把一些无效的链接挡在了启动线程以前,减小了这部分资源的浪费(由于咱们都知道每建立一个线程,就要为这个线程分配必定的内存空间)
AIO比NIO的进一步改善之处是将一些暂时可能无效的请求挡在了启动线程以前,好比在NIO的处理方式中,当一个请求来的话,开启线程进行处理,但这个请求所须要的资源尚未就绪,此时必须等待后端的应用资源,这时线程就被阻塞了。
适用场景分析:
BIO方式适用于链接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4之前的惟一选择,但程序直观简单易理解,如以前在Apache中使用。
NIO方式适用于链接数目多且链接比较短(轻操做)的架构,好比聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持,如在 Nginx,Netty中使用。
AIO方式使用于链接数目多且链接比较长(重操做)的架构,好比相册服务器,充分调用OS参与并发操做,编程比较复杂,JDK7开始支持,在成长中,Netty曾经使用过,后来放弃。
七、NIO、BIO与AIO:http://blog.51cto.com/stevex/1284437
九、.Java中的NIO,BIO,AIO分别是什么#
BIO:同步并阻塞,服务器实现模式为一个链接一个线程,即客户端有链接请求时服务器端就须要启动一个线程进行处理,若是这个链接不作任何事情会形成没必要要的线程开销,固然能够经过线程池机制改善。BIO方式适用于链接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4之前的惟一选择,但程序直观简单易理解。
NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的链接请求都会注册到多路复用器上,多路复用器轮询到链接有I/O请求时才启动一个线程进行处理。NIO方式适用于链接数目多且链接比较短(轻操做)的架构,好比聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
AIO:异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理.AIO方式使用于链接数目多且链接比较长(重操做)的架构,好比相册服务器,充分调用OS参与并发操做,编程比较复杂,JDK7开始支持。
十、IO和NIO区别#
一.IO是面向流的,NIO是面向缓冲区的。
二.IO的各类流是阻塞的,NIO是非阻塞模式。
三.Java NIO的选择器容许一个单独的线程来监视多个输入通道,你能够注册多个通道使用一个选择器,而后使用一个单独的线程来“选择”通道:这些通道里已经有能够处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。
1三、Java?IO与NIO
NIO是为了弥补IO操做的不足而诞生的,NIO的一些新特性有:非阻塞I/O,选择器,缓冲以及管道。管道(Channel),缓冲(Buffer) ,选择器( Selector)是其主要特征。
概念解释
Channel——管道实际上就像传统IO中的流,到任何目的地(或来自任何地方)的全部数据都必须经过一个 Channel 对象。一个 Buffer 实质上是一个容器对象。
每一种基本 Java 类型都有一种缓冲区类型:
ByteBuffer——byte
CharBuffer——char
ShortBuffer——short
IntBuffer——int
LongBuffer——long
FloatBuffer——float
DoubleBuffer——double
Selector——选择器用于监听多个管道的事件,使用传统的阻塞IO时咱们能够方便的知道何时能够进行读写,而使用非阻塞通道,咱们须要一些方法来知道何时通道准备好了,选择器正是为这个须要而诞生的。
NIO和传统的IO有什么区别呢?
IO是面向流的,NIO是面向块(缓冲区)的。
IO面向流的操做一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。,致使了数据的读取和写入效率不佳。
NIO面向块的操做在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多,同时数据读取到一个它稍后处理的缓冲区,须要时可在缓冲区中先后移动。这就增长了处理过程当中的灵活性。通俗来讲,NIO采起了“预读”的方式,当你读取某一部分数据时,他就会猜想你下一步可能会读取的数据而预先缓冲下来。
IO是阻塞的,NIO是非阻塞的
对于传统的IO,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据彻底写入。该线程在此期间不能再干任何事情了。
而对于NIO,使用一个线程发送读取数据请求,没有获得响应以前,线程是空闲的,此时线程能够去执行别的任务,而不是像IO中那样只能等待响应完成。
NIO和IO适用场景
NIO是为弥补传统IO的不足而诞生的,可是尺有所短寸有所长,NIO也有缺点,由于NIO是面向缓冲区的操做,每一次的数据处理都是对缓冲区进行的,那么就会有一个问题,在数据处理以前必需要判断缓冲区的数据是否完整或者已经读取完毕,若是没有,假设数据只读取了一部分,那么对不完整的数据处理没有任何意义。因此每次数据处理以前都要检测缓冲区数据。
那么NIO和IO各适用的场景是什么呢?
若是须要管理同时打开的成千上万个链接,这些链接每次只是发送少许的数据,例如聊天服务器,这时候用NIO处理数据多是个很好的选择。
而若是只有少许的链接,而这些链接每次要发送大量的数据,这时候传统的IO更合适。使用哪一种处理数据,须要在数据的响应等待时间和检查缓冲区数据的时间上做比较来权衡选择。
通俗解释,最后,对于NIO和传统IO
有一个网友讲的生动的例子:
之前的流老是堵塞的,一个线程只要对它进行操做,其它操做就会被堵塞,也就至关于水管没有阀门,你伸手接水的时候,无论水到了没有,你就都只能耗在接水(流)上。
nio的Channel的加入,至关于增长了水龙头(有阀门),虽然一个时刻也只能接一个水管的水,但依赖轮换策略,在水量不大的时候,各个水管里流出来的水,均可以获得妥
善接纳,这个关键之处就是增长了一个接水工,也就是Selector,他负责协调,也就是看哪根水管有水了的话,在当前水管的水接到必定程度的时候,就切换一下:临时关上当
前水龙头,试着打开另外一个水龙头(看看有没有水)。
当其余人须要用水的时候,不是直接去接水,而是事前提了一个水桶给接水工,这个水桶就是Buffer。也就是,其余人虽然也可能要等,但不会在现场等,而是回家等,能够作
其它事去,水接满了,接水工会通知他们。
这其实也是很是接近当前社会分工细化的现实,也是统分利用现有资源达到并发效果的一种很经济的手段,而不是动不动就来个并行处理,虽然那样是最简单的,但也是最浪费资源的方式。
算法
一、TreeMap如何插入数据:二叉树的左旋,右旋,双旋;
二、个排序以后的数组,插入数据,能够使用什么方法?答:二分法;问:时间复杂度是多少?
三、平衡二叉树的时间复杂度;
四、Hash算法和二叉树算法分别何时用;
五、图的广度优先算法和深度优先算法:详见jvm中垃圾回收实现;
六、链表,栈,队列,二叉树:
http://blog.csdn.net/zhaojw_420/article/details/68485474
七、八大排序算法:
八、查找算法
九、.队列:http://blog.csdn.net/javazejian/article/details/53375004
十、.堆栈:http://blog.csdn.net/javazejian/article/details/53362993
十一、.链表:http://blog.csdn.net/jianyuerensheng/article/details/51200274
十二、.树:[二叉树]http://blog.csdn.net/javazejian/article/details/53727333
[B树]http://blog.csdn.net/liuquan0071/article/details/50521032
[哈夫曼树]http://blog.csdn.net/axi295309066/article/details/54019807
1三、.(图)广度优先、深度优先:https://segmentfault.com/a/1190000002685939
1四、.常见排序算法:https://www.cnblogs.com/qqzy168/archive/2013/08/03/3219201.html
1五、.常见查找算法:http://blog.csdn.net/wqc_csdn/article/details/52691019
1六、.hash原理:http://blog.csdn.net/tanggao1314/article/details/51457585
1七、.hashmap实现:http://www.javashuo.com/article/p-kjwdvdbc-ke.html
1八、B+树
1九、快速排序,堆排序,插入排序(其实八大排序算法都应该了解
20、一致性Hash算法,一致性Hash算法的应用
2一、.深度优先和广度优先算法#
推荐看书籍复习!可参考文章:
http://blog.163.com/zhoumhan_0351/blog/static/3995422720098342257387/
http://blog.163.com/zhoumhan_0351/blog/static/3995422720098711040303/
http://blog.csdn.net/andyelvis/article/details/1728378
http://driftcloudy.iteye.com/blog/782873
2二、排序算法及对应的时间复杂度和空间复杂度#
推荐看书籍复习!可参考文章:
http://www.cnblogs.com/liuling/p/2013-7-24-01.html
http://blog.csdn.net/cyuyanenen/article/details/51514443
http://blog.csdn.net/whuslei/article/details/6442755
2三、排序算法编码实现#
参考http://www.cnblogs.com/liuling/p/2013-7-24-01.html
2四、.查找算法#
参考http://sanwen8.cn/p/142Wbu5.html
2五、.B+树#
参考http://www.cnblogs.com/syxchina/archive/2011/03/02/2197251.html
2六、.KMP算法#
推荐阅读数据复习!参考http://www.cnblogs.com/c-cloud/p/3224788.html
2七、.hash算法及经常使用的hash算法#
参考http://www.360doc.com/content/13/0409/14/10384031_277138819.shtml
2八、.如何判断一个单链表是否有环#
参考文章:
http://www.jianshu.com/p/0e28d31600dd
http://my.oschina.net/u/2391658/blog/693277?p={{totalPage}}
30、谈谈红黑树
答:算法和数据结构一直是我薄弱之处,这方面说本身补吧,成效不大,这里我就推荐一个:红黑树
3一、举例说说几个排序,并说明其排序原理
答:这里我就不细说了,你们本身看看 Java实现几种常见的排序算法
其余
1四、tcp/ip协议簇;
1五、osi五层网络协议;
1六、tcp,udp区别;
2三、进程通信的方式:消息队列,共享内存,信号量,socket通信等;
2九、TCP的三次握手和四次挥手
30、单例模式,工厂模式,建造者模式,观察者模式,适配器模式,代理模式等等
3二、Java8比Java7添加了什么新的特性
A:Lambda、streams、接口默认方法……
3三、 Java自带线程池判断线程池是否已经结束运行的方法叫什么:isShutdown和isTerminated。
3四、BlockingQueue
,CountDownLatch
及Semeaphore
的使用场景
3六、 若是要从LinkedBlockingQueue
中取出头部对象,分别哪一个方法会返回null、抛错、阻塞:take - 阻塞,poll - 返回null,remove - 抛错
44. 说说http,https协议
HTTP:
是互联网上应用最为普遍的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它能够使浏览器更加高效,使网络传输减小。
HTTPS:
是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,所以加密的详细内容就须要SSL。
区别:
一、https协议须要到ca申请证书,通常免费证书较少,于是须要必定费用。
二、http是超文本传输协议,信息是明文传输,https则是具备安全性的ssl加密传输协议。
三、http和https使用的是彻底不一样的链接方式,用的端口也不同,前者是80,后者是443。
四、http的链接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
45. 说说tcp/ip协议族
TCP/IP协议族是一个四层协议系统,自底而上分别是数据链路层、网络层、传输层和应用层。每一层完成不一样的功能,且经过若干协议来实现,上层协议使用下层协议提供的服务。
一、数据链路层负责帧数据的传递。
二、网络层责数据怎样传递过去。
三、传输层负责传输数据的控制(准确性、安全性)
四、应用层负责数据的展现和获取。
4六、tcp五层网络协议
物理层:
为数据端设备提供传送数据的通路,数据通路能够是一个物理媒体,也能够是多个物理媒体链接而成。
数据链路层:
为网络层提供数据传送服务。
网络层:
路由选择和中继、激活,终止网络链接、在一条数据链路上复用多条网络链接,多采起分时复用技术 、差错检测与恢复、排序,流量控制、服务选择、网络管理 。
传输层:
传输层是两台计算机通过网络进行数据通讯时,第一个端到端的层次,具备缓冲做用。
应用层:
应用层向应用程序提供服务
4七、TCP与UDP的区别
一、基于链接与无链接
二、TCP要求系统资源较多,UDP较少;
三、UDP程序结构较简单
四、流模式(TCP)与数据报模式(UDP);
五、TCP保证数据正确性,UDP可能丢包
六、TCP保证数据顺序,UDP不保证
4九、TCP长链接和短链接:http://www.javashuo.com/article/p-vobwkkvc-dq.html
50、.TCP与UDP区别:http://blog.csdn.net/li_ning_/article/details/52117463
5一、.TCP三次握手四次挥手过程:http://www.javashuo.com/article/p-hvkgbelr-cs.html
5二、.http几个重要概念:http://blog.csdn.net/drixe/article/details/1893558
5三、.http的报文结构:http://blog.csdn.net/zhangliang_571/article/details/23508953
5四、.GET/POST以及幂等性:http://blog.csdn.net/dongzhiquan/article/details/6113966
5五、.http request的几种类型:http://www.javashuo.com/article/p-vfuhzuiq-dz.html
5六、.http几个版本之间的区别:http://blog.csdn.net/zocojoker/article/details/53868639
6六、一个ArrayList在循环过程当中删除,会不会出问题,为何。
6八、三次握手,四次挥手,为何要四次挥手。
6九、长链接和短链接。
7一、.OSI七层模型以及TCP/IP四层模型#
参考文章:
http://blog.csdn.net/sprintfwater/article/details/8751453
http://www.cnblogs.com/commanderzhu/p/4821555.html
http://blog.csdn.net/superjunjin/article/details/7841099
7三、.HTTP报文内容#
参考文章:
https://yq.aliyun.com/articles/44675
http://www.cnblogs.com/klguang/p/4618526.html
http://my.oschina.net/orgsky/blog/387759
7四、get提交和post提交的区别#
参考文章:
http://www.cnblogs.com/hyddd/archive/2009/03/31/1426026.html
http://www.jellythink.com/archives/806
7六、TCP的三次握手和四次挥手#
阅读http://www.jianshu.com/p/f7d1010fa603
7七、.TCP和UDP区别#
参考http://www.cnblogs.com/bizhu/archive/2012/05/12/2497493.html
8三、Excption与Error包结构。OOM你遇到过哪些状况,SO F你遇到过哪些状况
Throwable是 Java 语言中全部错误或异常的超类。 Throwable包含两个子类: Error 和 Exception 。它们一般用于指示发生了异常状况。 Throwable包含了其线程建立时线程执行堆栈的快照,它提供了printStackTrace()等接口用于获取堆栈跟踪数据等信息。
Java将可抛出(Throwable)的结构分为三种类型:
被检查的异常(Checked Exception)。 运行时异常(RuntimeException)。 错误(Error)。
运行时异常RuntimeException
定义 : RuntimeException及其子类都被称为运行时异常。 特色 : Java编译器不会检查它 也就是说,当程序中可能出现这类异常时,假若既"没有经过throws声明抛出它",也"没有用try-catch语句捕获它",仍是会编译经过。
例如,除数为零时产生的ArithmeticException异常,数组越界时产生的IndexOutOfBoundsException异常,fail-fail机制产生的ConcurrentModificationException异常等,都属于运行时异常。
堆内存溢出 OutOfMemoryError(OOM)
除了程序计数器外,虚拟机内存的其余几个运行时区域都有发生OutOfMemoryError(OOM)异常的可能。
Java Heap 溢出。 通常的异常信息:java.lang.OutOfMemoryError:Java heap spacess。 java堆用于存储对象实例,咱们只要不断的建立对象,而且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,就会在对象数量达到最大堆容量限制后产生内存溢出异常。
堆栈溢出 StackOverflow (SOF)
StackOverflowError 的定义: 当应用程序递归太深而发生堆栈溢出时,抛出该错误。 由于栈通常默认为1-2m,一旦出现死循环或者是大量的递归调用,在不断的压栈过程当中,形成栈容量超过1m而致使溢出。
栈溢出的缘由:
递归调用。 大量循环或死循环。 全局变量是否过多。 数组、List、map数据过大。
8九、foreach与正常for循环效率对比
用for循环arrayList 10万次花费时间:5毫秒。 用foreach循环arrayList 10万次花费时间:7毫秒。 用for循环linkList 10万次花费时间:4481毫秒。 用foreach循环linkList 10万次花费时间:5毫秒。
循环ArrayList时,普通for循环比foreach循环花费的时间要少一点。 循环LinkList时,普通for循环比foreach循环花费的时间要多不少。
当我将循环次数提高到一百万次的时候,循环ArrayList,普通for循环仍是比foreach要快一点;可是普通for循环在循环LinkList时,程序直接卡死。
ArrayList:ArrayList是采用数组的形式保存对象的,这种方式将对象放在连续的内存块中,因此插入和删除时比较麻烦,查询比较方便。
LinkList:LinkList是将对象放在独立的空间中,并且每一个空间中还保存下一个空间的索引,也就是数据结构中的链表结构,插入和删除比较方便,可是查找很麻烦,要从第一个开始遍历。
结论:
须要循环数组结构的数据时,建议使用普通for循环,由于for循环采用下标访问,对于数组结构的数据来讲,采用下标访问比较好。
须要循环链表结构的数据时,必定不要使用普通for循环,这种作法很糟糕,数据量大的时候有可能会致使系统崩溃。
90、java反射的做用于原理
什么是Java的反射呢?
Java 反射是可让咱们在运行时,经过一个类的Class对象来获取它获取类的方法、属性、父类、接口等类的内部信息的机制。
这种动态获取信息以及动态调用对象的方法的功能称为JAVA的反射。
反射的做用?
反射就是:在任意一个方法里:
1.若是我知道一个类的名称/或者它的一个实例对象, 我就能把这个类的全部方法和变量的信息找出来(方法名,变量名,方法,修饰符,类型,方法参数等等全部信息)
2.若是我还明确知道这个类里某个变量的名称,我还能获得这个变量当前的值。
3.固然,若是我明确知道这个类里的某个方法名+参数个数类型,我还能经过传递参数来运行那个类里的那个方法。
反射机制主要提供了如下功能:
在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具备的成员变量和方法。
在运行时调用任意一个对象的方法。
生成动态代理。
9一、反射的原理?
JAVA语言编译以后会生成一个.class文件,反射就是经过字节码文件找到某一个类、类中的方法以及属性等。
反射的实现API有哪些?
反射的实现主要借助如下四个类:
Class:类的对象
Constructor:类的构造方法
Field:类中的属性对象
Method:类中的方法对象
反射的实例
blog.csdn.net/xuefeng_yan…
www.cnblogs.com/zhaoyanjun/…
9二、泛型经常使用特色
List<String>可否转为List<Object>
不能够强转类型的
这个问题涉及到了,范型向上转型 和 范型向下转型问题。 List向上转换至List(等价于List)会丢失String类的身份(String类型的特有接口)。 当须要由List向下转型时,你的程序必须明确的知道将对象转换成何种具体类型,否则这将是不安全的操做。
若是要强转类型,Json 序列化转型
List<String> str = new ArrayList<String>();
List<Object> obj= JSONObject.parseArray(JSONObject.toJSONString(str));
或者遍历,或者克隆,可是取出来就是(Object)了,须要强转,String 由于类型丢了。
9五、Java1.7与1.8,1.9,10 新特性
1.5
自动装箱与拆箱
枚举(经常使用来设计单例模式)
静态导入
可变参数
内省
1.6
Web服务元数据
脚本语言支持
JTable的排序和过滤
更简单,更强大的JAX-WS
轻量级Http Server
嵌入式数据库 Derby
1.7
switch中能够使用字串了
运用List tempList = new ArrayList<>(); 即泛型实例化类型自动推断
语法上支持集合,而不必定是数组
新增一些取环境信息的工具方法
Boolean类型反转,空指针安全,参与位运算
两个char间的equals
安全的加减乘除
map集合支持并发请求,且能够写成 Map map = {name:"xxx",age:18};
1.8
容许在接口中有默认方法实现
Lambda表达式
函数式接口
方法和构造函数引用
Lambda的范围
内置函数式接口
Streams
Parallel Streams
Map
时间日期API
Annotations
1.9
Jigsaw 项目;模块化源码
简化进程API
轻量级 JSON API
钱和货币的API
改善锁争用机制
代码分段缓存
智能Java编译, 第二阶段
HTTP 2.0客户端
Kulla计划: Java的REPL实现
10
本地变量类型推断
统一JDK仓库
垃圾回收器接口
G1的并行Full GC
应用程序类数据共享
ThreadLocal握手机制
设计模式:单例、工厂、适配器、责任链、观察者等等
【示例】设计模式——单例模式、工厂模式、代理模式、观察者模式、装饰器模式
blog.csdn.net/learrrrrrrr…
菜鸟教程-设计模式
www.runoob.com/design-patt…
9六、什么是设计模式
设计模式是一种解决方案,用于解决在软件设计中广泛存在的问题,是前辈们对以前软件设计中反复出现的问题的一个总结。
咱们学设计模式,是为了学习如何合理的组织咱们的代码,如何解耦,如何真正的达到对修改封闭对扩展开放的效果,而不是去背诵那些类的继承模式,而后本身记不住,回过头来就骂设计模式把你的代码搞复杂了,要反设计模式。
设计模式的六大原则
开闭原则:实现热插拔,提升扩展性。
里氏代换原则:实现抽象的规范,实现子父类互相替换;
依赖倒转原则:针对接口编程,实现开闭原则的基础;
接口隔离原则:下降耦合度,接口单独设计,互相隔离;
迪米特法则,又称不知道原则:功能模块尽可能独立;
合成复用原则:尽可能使用聚合,组合,而不是继承;
一、开闭原则(Open Close Principle)
开闭原则的意思是:对扩展开放,对修改关闭。在程序须要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,咱们须要使用接口和抽象类,后面的具体设计中咱们会提到这点。
二、里氏代换原则(Liskov Substitution Principle)
里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则中说,任何基类能够出现的地方,子类必定能够出现。LSP 是继承复用的基石,只有当派生类能够替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也可以在基类的基础上增长新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,因此里氏代换原则是对实现抽象化的具体步骤的规范。
三、依赖倒转原则(Dependence Inversion Principle)
这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。
四、接口隔离原则(Interface Segregation Principle)
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另一个意思是:下降类之间的耦合度。因而可知,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调下降依赖,下降耦合。
五、迪米特法则,又称最少知道原则(Demeter Principle)
最少知道原则是指:一个实体应当尽可能少地与其余实体之间发生相互做用,使得系统功能模块相对独立。
六、合成复用原则(Composite Reuse Principle)
合成复用原则是指:尽可能使用合成/聚合的方式,而不是使用继承。
9八、数据库存储日期格式时,如何考虑时区转换问题?
答:使用TimeStamp , 缘由参照:Java编程中遇到的时区转换问题
9九、HTTP协议,GET和POST 的区别
解答:单例模式的7中用法
10一、如何看待设计模式,并简单说说你对观察者模式的理解
10三、序列化的原理和做用
答:Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization是一种将这些字节重建成一个对象的过程,主要用于HTTP或者WebService接口传输过程当中对象参数的传播,具体可参看:Java序列化机制和原理
网络协议方面,考察最多的包括服务器和客户端在三次握手、四次挥手过程当中的状态变化;还有网络拥塞控制,及其解决办法等。
10四、三次握手、四次挥手示意图:
总共有四种状态:主动创建链接、主动断开链接、被动创建连和被动断开链接
两两组合仍是 4 种组合:
10五、滑动窗口机制
由发送方和接收方在三次握手阶段,互相将本身的最大可接收的数据量告诉对方。也就是本身的数据接收缓冲池的大小。这样对方能够根据已发送的数据量来计算是否能够接着发送。
在处理过程当中,当接收缓冲池的大小发生变化时,要给对方发送更新窗口大小的通知。
10六、拥塞避免机制
拥塞:对资源的需求超过了可用的资源。若网络中许多资源同时供应不足,网络的性能就要明显变坏,整个网络的吞吐量随之负荷的增大而降低。
拥塞控制:防止过多的数据注入到网络中,使得网络中的路由器或链路不致过载。
拥塞控制方法:
10七、浏览器中输入:“www.xxx.com” 以后都发生了什么?请详细阐述。
解析:经典的网络协议问题。
答:
10八、常见 HTTP 状态码
10九、TCP 和 UDP 的区别:
答:
限于篇幅,更多网络协议相关知识,请参阅个人博客:TCP/IP 协议面试常问知识点,倾心总结
小结:必须熟练掌握 TCP 和 UDP 的区别、三次握手和四次挥手的状态切换,必考。
核心篇
数据存储
一、MySQL 索引使用的注意事项
三、说说分库与分表设计
四、分库与分表带来的分布式困境与应对之策
五、说说 SQL 优化之道
六、MySQL 遇到的死锁问题
七、存储引擎的 InnoDB 与 MyISAM
八、数据库索引的原理
九、为何要用 B-tree
十一、limit 20000 加载很慢怎么解决:采用id排序,经过id来限制范围
十二、选择合适的分布式主键方案
1三、选择合适的数据存储方案
1四、ObjectId 规则
1六、倒排索引
1七、聊聊 ElasticSearch 使用场景
1八、
索引:B+,B-,全文索引
Mysql的索引是一个数据结构,旨在使数据库高效的查找数据。
经常使用的数据结构是B+Tree,每一个叶子节点不但存放了索引键的相关信息还增长了指向相邻叶子节点的指针,这样就造成了带有顺序访问指针的B+Tree,作这个优化的目的是提升不一样区间访问的性能。
何时使用索引:
常常出如今group by,order by和distinc关键字后面的字段
常常与其余表进行链接的表,在链接字段上应该创建索引
常常出如今Where子句中的字段
常常出现用做查询选择的字段
友情连接:MySQL:InnoDB存储引擎的B+树索引算法
友情连接:MySQL索引背后的数据结构及算法原理
1九、
数据库事务是指做为单个逻辑工做单元执行的一系列操做。
友情连接:数据库事务的四大特性以及事务的隔离级别
20、
MySQL数据库优化总结
MYSQL 优化经常使用方法
MySQL存储引擎--MyISAM与InnoDB区别
关于SQL数据库中的范式
2一、mysql优化经验:
2三、mysql的索引分类:B+,hash;什么状况用什么索引;
2四、mysql的存储引擎有哪些,区别是什么;
2五、说说事务的特性和隔离级别;
2六、mysql面试题:
http://blog.csdn.net/zhaojw_420/article/details/70530664
2七、sql优化:
http://blog.csdn.net/zhaojw_420/article/details/70532017
2八、mysql分页有什么优化
2九、悲观锁、乐观锁:版本号检测为乐观锁,其余为悲观锁
30、组合索引,最左原则
3一、mysql 的表锁、行锁
3三、mysql的索引分类:B+,hash;什么状况用什么索引
3四、事务的特性和隔离级别
36. 若是查询很慢,你会想到的第⼀个⽅式是什么?索引是⼲嘛的?
37. 若是建了⼀个单列索引,查询的时候查出2列,会⽤到这个单列索引吗?:会
38. 若是建了⼀个包含多个列的索引,查询的时候只⽤了第⼀列,能不能⽤上 这个索引?查三列呢?:最左原则
40. 怎么看是否⽤到了某个索引?:explain执行计划看type
45. 大家的数据库单表数据量是多少?⼀般多⼤的时候开始出现查询性能急 剧降低?:1000万|mysql写入速度是100k/s
47. 读写分离是怎么作的?你认为中间件会怎么来操做?这样操做跟事务有什么关系?:mysql主从复制,读所有打到从,写所有打到主|中间件会解析sql分析读写操做|主从同步延迟引发的事务一致性问题?
14. 分库分表有没有作过?线上的迁移过程是怎么样的?如何肯定数据是正 确的?:在老库上挂上精卫,订阅精卫任务将数据写入分库分表
52. MySQL为何使用B+树做为索引?
5三、msyql优化经验
一、对查询进行优化,应尽可能避免全表扫描,首先应考虑在 where 及 order by 涉及的列上创建索引。
二、应尽可能避免在 where 子句中使用!=或<>操做符,不然引擎将放弃使用索引而进行全表扫描。
三、尽可能使用数字型字段,若只含数值信息的字段尽可能不要设计为字符型,这会下降查询和链接的性能,并会增长存储开销。这是由于引擎在处理查询和链接时会逐个比较字符串中每个字符,而对于数字型而言只须要比较一次就够了。
四、任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
五、避免频繁建立和删除临时表,以减小系统表资源的消耗。诸如此类,等等等等......
5四、.各个数据库引擎区别:http://www.jb51.net/article/38004.htm
5五、.索引的使用注意事项:http://www.javashuo.com/article/p-cubihmaj-cn.html
5七、常见的数据库优化手段
5八、索引的优缺点,什么字段上创建索引:order by, where ,group by,distinct,join等字段
5九、数据库链接池。:原理?
6一、产生死锁的必要条件#
参考http://blog.sina.com.cn/s/blog_5e3604840100ddgq.html
6二、死锁预防#
参考http://blog.sina.com.cn/s/blog_5e3604840100ddgq.html
6四、.数据库事务隔离级别#
参考http://blog.csdn.net/fg2006/article/details/6937413
6五、.数据库链接池的原理#
参考http://blog.csdn.net/shuaihj/article/details/14223015
6六、.乐观锁和悲观锁#
参考http://www.open-open.com/lib/view/open1452046967245.html
6七、.如何实现不一样数据库的数据查询分页#
参考http://blog.csdn.net/yztezhl/article/details/20489387
6九、.数据库索引的实现(B+树介绍、和B树、R树区别)#
参考文章:
http://blog.csdn.net/kennyrose/article/details/7532032
http://www.xuebuyuan.com/2216918.html
70、.SQL性能优化#
参考文章:
http://database.51cto.com/art/200904/118526.htm
http://www.cnblogs.com/rootq/archive/2008/11/17/1334727.html
7一、数据库索引的优缺点以及何时数据库索引失效#:not in,!=不会命中索引
参考文章:
http://www.cnblogs.com/mxmbk/articles/5226344.html
http://www.cnblogs.com/simplefrog/archive/2012/07/15/2592527.html
http://www.open-open.com/lib/view/open1418476492792.html
http://blog.csdn.net/colin_liu2009/article/details/7301089
http://www.cnblogs.com/hongfei/archive/2012/10/20/2732589.html
7二、当数据表中A、B字段作了组合索引,那么单独使用A或单独使用B会有索引效果吗?(使用like查询如何有索引效果)
答:看A、B两字段作组合索引的时候,谁在前面,谁在后面,若是A在前,那么单独使用A会有索引效果,单独使用B则没有,反之亦然。同理,使用like模糊查询时,若是只是使用前面%,那么有索引效果,若是使用双%号匹配,那么则无索引效果
7三、mysql查询字段区不区分大小写?
解答:不区分,哪怕值也不区分
解答:数据库负载均衡和集群参考 ,参考2
7七、一条sql执行过长的时间,你如何优化,从哪些方面?
答:
一、查看sql是否涉及多表的联表或者子查询,若是有,看是否能进行业务拆分,相关字段冗余或者合并成临时表(业务和算法的优化)
二、涉及链表的查询,是否能进行分表查询,单表查询以后的结果进行字段整合
三、若是以上两种都不能操做,非要链表查询,那么考虑对相对应的查询条件作索引。加快查询速度
四、针对数量大的表进行历史表分离(如交易流水表)
五、数据库主从分离,读写分离,下降读写针对同一表同时的压力,至于主从同步,mysql有自带的binlog实现 主从同步
六、explain分析sql语句,查看执行计划,分析索引是否用上,分析扫描行数等等
七、查看mysql执行日志,看看是否有其余方面的问题
我的理解:从根本上来讲,查询慢是占用mysql内存比较多,那么能够从这方面去酌手考虑
7八、Mysql的事物隔离级别?
答:Mysql的事物隔离级别 其实跟 Spring的事物隔离级别同样,都是一、Read Uncommitted(读取未提交内容), 二、Read Committed(读取提交内容),三、Repeatable Read(可重读),四、Serializable(可串行化) 具体参照:mysql事物隔离级别
7九、Mysql索引的原理
答:索引的做用你们都知道,就是加快查询速度,可是原理,我说不上来,这里直接看吧:Mysql索引工做原理
80、MySQL 和 MongoDB 的区别有哪些?如何选择?
8一、MongoDB 的优缺点有哪些?
(ps 本人对这一块不是很熟悉,就不附上参考答案了,请各位小伙伴自行学习哈~)
8二、据说过事务吗?(必考)
答:做为单个逻辑工做单元执行的一系列操做,知足四大特性:
原子性(Atomicity):事务做为一个总体被执行 ,要么所有执行,要么所有不执行;
一致性(Consistency):保证数据库状态从一个一致状态转变为另外一个一致状态;
隔离性(Isolation):多个事务并发执行时,一个事务的执行不该影响其余事务的执行;
持久性(Durability):一个事务一旦提交,对数据库的修改应该永久保存。
8三、事务的并发问题有哪几种?
答:丢失更新、脏读、不可重复读以及幻读。
8四、数据库中的锁有哪几种?
答:独占锁、排他锁以及更新锁。
8五、事务的隔离级别有哪几种?
答:读未提交、读已提交、可重复读和序列化。
扩展问题:MySQL 事务默认隔离级别是哪一个?
答:可重复读。
8六、数据库的索引有什么做用?(必考) 底层数据结构是什么,为何使用这种数据结构?
答:
索引 是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息;
底层数据结构是 B+ 树;
使用 B+ 树的缘由:查找速度快、效率高,在查找的过程当中,每次都能抛弃掉一部分节点,减小遍历个数。( 此时,你应该在白纸上画出什么是 B+ 树 )
扩展问题:聚簇索引和非聚簇索引的区别?
8七、MyISAM 和 InnoDB 的区别有哪些?
答:
MyISAM 不支持事务,InnoDB 是事务类型的存储引擎;
MyISAM 只支持表级锁,BDB 支持页级锁和表级锁,默认为页级锁;而 InnoDB 支持行级锁和表级锁,默认为行级锁;
MyISAM 引擎不支持外键,InnoDB 支持外键;
MyISAM 引擎的表在大量高并发的读写下会常常出现表损坏的状况;
对于 count( ) 查询来讲 MyISAM 更有优点;
InnoDB 是为处理巨大数据量时的最大性能设计,它的 CPU 效率多是任何其它基于磁盘的关系数据库引擎所不能匹敌的;
MyISAM 支持全文索引(FULLTEXT),InnoDB 不支持;
MyISAM 引擎的表的查询、更新、插入的效率要比 InnoDB 高。
最主要的区别是:MyISAM 表不支持事务、不支持行级锁、不支持外键。 InnoDB 表支持事务、支持行级锁、支持外键。(可直接回答这个)
缓存使用
一、Redis 有哪些类型
二、Redis 内部结构
三、聊聊 Redis 使用场景:缓存,队列
四、Redis 持久化机制
五、Redis 如何实现持久化
六、Redis 集群方案与实现
七、Redis 为何是单线程的:缓存主要是io密集型,对cpu需求不大,因此单线程已经知足要求
八、缓存奔溃
九、缓存降级
十、使用缓存的合理性问题
十一、Redis数据结构:String,Hash,List,Set,Sorted Set
十二、redis和memcache的区别:数据结构不同|redis单线程|mc读性能更高
1三、用redis作过什么:cache,队列
1四、redis是如何持久化的:rdb和aof
1五、redis集群如何同步:数据复制,slave发起请求,master push数据
1六、redis的数据添加过程是怎样的:哈希槽
1七、redis的淘汰策略有哪些:volatile-lru,volatile-ttl,volatile-random,allkeys-lru,allkeys-random,no-enviction
20、Redis用过哪些数据数据,以及Redis底层怎么实现
2一、Redis缓存穿透,缓存雪崩
2二、如何使用Redis来实现分布式锁:setnx
2三、Redis的并发竞争问题,以及如何解决:乐观锁,watch
2四、Redis持久化的几种方式,优缺点是什么,怎么实现的:aof(每一个操做一个脚本),rdb(定时全两快照)
2五、Redis的缓存失效策略
2六、Redis集群,高可用,原理
2七、Redis缓存分片
31.渐进式rehash过程?:同时持有两个hash,逐渐迁移
32.rehash源码?
34.redis aof源码?
35.事务与事件:事件IO多路复用,reactor模型
36.主从复制:
37.启动过程
38.集群
4二、redis的两个持久化策略:http://blog.csdn.net/u010785685/article/details/52366977
4三、.redis如何事务支持:http://www.javashuo.com/article/p-cjvuqfnz-eh.html
4四、.redis哨兵机制:http://blog.csdn.net/zbw18297786698/article/details/52891695
4五、.redis集群方案:https://www.zhihu.com/question/21419897
4六、.redis主从同步策略:http://blog.csdn.net/sk199048/article/details/50725369
4六、redis是单线程的么,全部的工做都是单线程么。
4七、redis如何存储一个String的:char数组
4九、redis的哨兵模式,一个key值如何在redis集群中找到存储在哪里。
消息队列
一、消息队列的使用场景:异步,削峰|发邮件,发短信
二、消息的重发补偿解决思路
三、消息的幂等性解决思路
四、消息的堆积解决思路
五、本身如何实现消息队列
六、如何保证消息的有序性:根据业务id肯定路由到哪一个broker,保证同一个业务id路由到同一个broker
七、mq的原理是什么:有点大。。均可以说;
八、mq如何保证明时性;
九、mq的持久化是怎么作的;
框架篇
Spring
一、BeanFactory 和 ApplicationContext 有什么区别:Application支持父子容器,支持web。。。
二、Spring Bean 的生命周期:
三、Spring IOC 如何实现
四、说说 Spring AOP
五、Spring AOP 实现原理
六、动态代理(cglib 与 JDK)
七、Spring 事务实现方式
八、Spring 事务底层原理
九、如何自定义注解实现功能
十、Spring MVC 运行流程
十一、Spring MVC 启动流程
十二、Spring 的单例实现原理
1三、Spring 框架中用到了哪些设计模式
1四、Spring 其余产品(Srping Boot、Spring Cloud、Spring Secuirity、Spring Data、Spring AMQP 等)
1五、
Spring IOC (控制反转,依赖注入)
Spring支持三种依赖注入方式,分别是属性(Setter方法)注入,构造注入和接口注入。
在Spring中,那些组成应用的主体及由Spring IOC容器所管理的对象被称之为Bean。
Spring的IOC容器经过反射的机制实例化Bean并创建Bean之间的依赖关系。
简单地讲,Bean就是由Spring IOC容器初始化、装配及被管理的对象。
获取Bean对象的过程,首先经过Resource加载配置文件并启动IOC容器,而后经过getBean方法获取bean对象,就能够调用他的方法。
Spring Bean的做用域:
Singleton:Spring IOC容器中只有一个共享的Bean实例,通常都是Singleton做用域。
Prototype:每个请求,会产生一个新的Bean实例。
Request:每一次http请求会产生一个新的Bean实例。
友情连接: Spring框架IOC容器和AOP解析
友情连接:浅谈Spring框架注解的用法分析
友情连接:关于Spring的69个面试问答——终极列表
1六、
代理的共有优势:业务类只须要关注业务逻辑自己,保证了业务类的重用性。
Java静态代理:
代理对象和目标对象实现了相同的接口,目标对象做为代理对象的一个属性,具体接口实现中,代理对象能够在调用目标对象相应方法先后加上其余业务处理逻辑。
缺点:一个代理类只能代理一个业务类。若是业务类增长方法时,相应的代理类也要增长方法。
Java动态代理:
Java动态代理是写一个类实现InvocationHandler接口,重写Invoke方法,在Invoke方法能够进行加强处理的逻辑的编写,这个公共代理类在运行的时候才能明确本身要代理的对象,同时能够实现该被代理类的方法的实现,而后在实现类方法的时候能够进行加强处理。
实际上:代理对象的方法 = 加强处理 + 被代理对象的方法
JDK和CGLIB生成动态代理类的区别:
JDK动态代理只能针对实现了接口的类生成代理(实例化一个类)。此时代理对象和目标对象实现了相同的接口,目标对象做为代理对象的一个属性,具体接口实现中,能够在调用目标对象相应方法先后加上其余业务处理逻辑
CGLIB是针对类实现代理,主要是对指定的类生成一个子类(没有实例化一个类),覆盖其中的方法 。
Spring AOP应用场景
性能检测,访问控制,日志管理,事务等。
默认的策略是若是目标类实现接口,则使用JDK动态代理技术,若是目标对象没有实现接口,则默认会采用CGLIB代理
1七、
SpringMVC运行原理
客户端请求提交到DispatcherServlet
由DispatcherServlet控制器查询HandlerMapping,找到并分发到指定的Controller中。
Controller调用业务逻辑处理后,返回ModelAndView
DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图
视图负责将结果显示到客户端
友情连接:Spring:基于注解的Spring MVC(上)
友情连接: Spring:基于注解的Spring MVC(下)
友情连接:SpringMVC与Struts2区别与比较总结
友情连接:SpringMVC与Struts2的对比
1八、
Spring事务配置方法:
1.切点信息,用于定位实施事物切面的业务类方法
2.控制事务行为的事务属性,这些属性包括事物隔离级别,事务传播行为,超时时间,回滚规则。
Spring经过aop/tx Schema 命名空间和@Transaction注解技术来进行声明式事物配置。
2一、BeanFactory 和 FactoryBean?
2二、Spring IOC 的理解,其初始化过程?
2三、BeanFactory 和 ApplicationContext?
2四、Spring Bean 的生命周期,如何被管理的?
2五、Spring Bean 的加载过程是怎样的?
2六、若是要你实现Spring AOP,请问怎么实现?
2七、若是要你实现Spring IOC,你会注意哪些问题?:对象依赖管理,继承,反射
2八、Spring 是如何管理事务的,事务管理机制?
2九、Spring 的不一样事务传播行为有哪些,干什么用的?
30、Spring 中用到了那些设计模式?:抽象工厂,动态代理,观察者模式(Event)。。。
3二、Spring 循环注入的原理?
3三、Spring AOP的理解,各个术语,他们是怎么相互工做的?
3四、Spring 如何保证 Controller 并发的安全?
35. 你有没有⽤过Spring的AOP? 是⽤来⼲嘛的? ⼤概会怎么使⽤?
36. 若是⼀个接⼝有2个不一样的实现, 那么怎么来Autowire⼀个指定的实现?:Qualifier
37. Spring的声明式事务 @Transaction注解⼀般写在什么位置? 抛出了异常会⾃动回滚吗?有没有办法控制不触发回滚?
38. 若是想在某个Bean⽣成并装配完毕后执⾏⾃⼰的逻辑,能够什么⽅式实现?:Intialization接口afterProperties方法
39. SpringBoot没有放到web容器⾥为何能跑HTTP服务?:自带嵌入式tomcat
40. SpringBoot中若是你想使⽤⾃定义的配置⽂件⽽不只仅是 application.properties,应该怎么弄?
41. SpringMVC中RequestMapping能够指定GET, POST⽅法么?怎么指定?
42. SpringMVC若是但愿把输出的Object(例如XXResult或者XXResponse)这 种包装为JSON输出, 应该怎么处理?
43. 怎样拦截SpringMVC的异常,而后作⾃定义的处理,⽐如打⽇志或者包装成JSON
45. .struts2和springMVC的区别
46. spring框架中须要引用哪些jar包,以及这些jar包的用途
50. spring注入的几种方式
51. spring如何实现事物管理的
52. springIOC和AOP的原理
55. springmvc的核心是什么,请求的流程是怎么处理的,控制反转怎么实现的
核心:
控制反转和面向切面
请求处理流程:
一、首先用户发送请求到前端控制器,前端控制器根据请求信息(如URL)来决定选择哪个页面控制器进行处理并把请求委托给它,即之前的控制器的控制逻辑部分;
二、页面控制器接收到请求后,进行功能处理,首先须要收集和绑定请求参数到一个对象,并进行验证,而后将命令对象委托给业务对象进行处理;处理完毕后返回一个ModelAndView(模型数据和逻辑视图名);
三、前端控制器收回控制权,而后根据返回的逻辑视图名,选择相应的视图进行渲染,并把模型数据传入以便视图渲染;
四、前端控制器再次收回控制权,将响应返回给用户。
控制反转如何实现:
咱们每次使用spring框架都要配置xml文件,这个xml配置了bean的id和class。
spring中默认的bean为单实例模式,经过bean的class引用反射机制能够建立这个实例。
所以,spring框架经过反射替咱们建立好了实例而且替咱们维护他们。
A须要引用B类,spring框架就会经过xml把B实例的引用传给了A的成员变量。
5六、.spring的特色及好处:https://www.cnblogs.com/song1314/articles/4568379.html
5七、.spring的69面试题:http://www.javashuo.com/article/p-bucgmvli-es.html
5八、.spring简化java开发复杂性的策略:http://blog.csdn.net/running_nz/article/details/54583100
5九、.spring循环依赖及解决办法:http://blog.csdn.net/caomiao2006/article/details/46511123
60、.springmvc工做流程和原理:http://blog.csdn.net/liangzi_lucky/article/details/52459378
6一、.spring注解原理:http://blog.csdn.net/u010987379/article/details/52152795
6二、
Spring AOP 实现原理?
参考 :http://blog.csdn.net/moreevan/article/details/11977115/
6三、@transactional注解在什么状况下会失效,为何?:调用同一个类的方法的时候,spring容器经过aop提供为bean提供事务管理功能,方法内部调用是调用的对象自己的方法,不是调用的spring容器的bean
6四、SpringMVC的Controller是如何将参数和前端传来的数据一一对应的。
6五、Quartz是如何完成定时任务的。
6七、Spring使用了哪些设计模式。
6八、Spring的IOC有什么优点。
6九、Spring如何维护它拥有的bean。
70、.Struts中请求处理过程#
参考文章http://www.cnblogs.com/liuling/p/2013-8-10-01.html
7一、.MVC概念#
参考文章http://www.cnblogs.com/scwyh/articles/1436802.html
7二、.Springmvc与Struts区别#
参考文章:
http://blog.csdn.net/tch918/article/details/38305395
http://blog.csdn.net/chenleixing/article/details/44570681
7六、.Springbean的加载过程(推荐看Spring的源码)#
参考文章http://geeekr.com/read-spring-source-1-how-to-load-bean/
7七、.Springbean的实例化(推荐看Spring的源码)#
参考文章http://geeekr.com/read-spring-source-two-beans-initialization/
7八、.Spring如何实现AOP和IOC(推荐看Spring的源码)#
参考文章http://www.360doc.com/content/15/0116/21/12385684_441408260.shtml
7九、.Springbean注入方式#
参考文章http://blessht.iteye.com/blog/1162131
80、.Spring的事务管理#
这个主题的参考文章没找到特别好的,http://blog.csdn.net/trigl/article/details/50968079这个还能够。
8一、.Spring事务的传播特性#
参考文章http://blog.csdn.net/lfsf802/article/details/9417095
80、.springmvc原理
参考文章http://blog.sina.com.cn/s/blog_7ef0a3fb0101po57.html
8二、Spring 事务的隔离性,并说说每一个隔离性的区别
解答:Spring事务详解
解答:Spring事务详解
解答:Spring事务机制
解答:Spring4新特性
8八、SpringMVC的原理以及返回数据如何渲染到jsp/html上?
答:Spring MVC的核心就是 DispatcherServlet , 一个请求通过 DispatcherServlet ,转发给HandlerMapping ,而后经反射,对应 Controller及其里面方法的@RequestMapping地址,最后经ModelAndView和ViewResoler返回给对应视图 。 具体可参考:Spring MVC的工做原理
8九、Spring的原理
答:Spring的核心是IOC和AOP ,IOC是依赖注入和控制反转, 其注入方式可分为set注入、构造器注入、接口注入等等。IOC就是一个容器,负责实例化、定位、配置应用程序中的对象及创建这些对象间的依赖。简单理解就是:JAVA每一个业务逻辑处理至少须要两个或者以上的对象协做进行工做,可是每一个对象在使用它的合做对象的时候,都须要频繁的new 对象来实现,你就会发现,对象间的耦合度高了。而IOC的思想是:Spring容器来管理这些,对象只须要处理自己业务关系就行了。至于什么是控制反转,就是得到依赖对象的方式反转了。
AOP呢,面向切面编程,最直接的体现就是Spring事物管理。至于Spring事物的相关资料,就不细说了,参考:Spring注解式事物管理
JavaWeb 开发经典的 3 层框架:Web 层、Service 层(业务逻辑层)和 Dao 层(数据访问层)
Spring 知识点
90、Spring 的 IOC 和 AOP 有了解吗?
答:
9一、AOP 的实现方式有哪几种?如何选择?(必考)
答:JDK 动态代理实现和 cglib 实现。
选择:
扩展:JDK 动态代理如何实现?(加分点)
答:JDK 动态代理,只能对实现了接口的类生成代理,而不是针对类,该目标类型实现的接口都将被代理。原理是经过在运行期间建立一个接口的实现类来完成对目标对象的代理。
解析:关于 IOC 和 AOP 的详细阐述,请各位参阅个人博客:Spring 核心 AOP(面向切面编程)总结,Spring 框架学习—控制反转(IOC)
9二、Spring MVC 的核心控制器是什么?消息处理流程有哪些?
答:核心控制器为 DispatcherServlet。消息流程以下:
9三、其余问题包括:重定向和转发的区别、动态代理和静态代理的区别等。
Netty
一、为何选择 Netty
二、说说业务中,Netty 的使用场景:通讯组件,rpc通讯组件,mq通讯组件
三、原生的 NIO 在 JDK 1.7 版本存在 epoll bug
四、什么是TCP 粘包/拆包:链路层对数据进行拆分数据包和合并数据包
五、TCP粘包/拆包的解决办法:业务曾手动拆分数据包
六、Netty 线程模型
七、说说 Netty 的零拷贝:内核态,不用在用户态之间切换
八、Netty 内部执行流程
九、Netty 重连实现
十一、Netty 的各大组件
十二、Netty的线程模型
1三、TCP 粘包/拆包的缘由及解决方法
1四、了解哪几种序列化协议?包括使用场景和如何去选择
1六、Netty的高性能表如今哪些方面:nio
17.BIO、NIO和AIO的区别?
18.NIO的组成?
26.NIOEventLoopGroup源码?
MyBatis
一、
Mybatis
每个Mybatis的应用程序都以一个SqlSessionFactory对象的实例为核心。首先用字节流经过Resource将配置文件读入,而后经过SqlSessionFactoryBuilder().build方法建立SqlSessionFactory,而后再经过SqlSessionFactory.openSession()方法建立一个SqlSession为每个数据库事务服务。
经历了Mybatis初始化 –>建立SqlSession –>运行SQL语句,返回结果三个过程
三、mybatis如何处理结果集
MyBatis的结果集是经过反射来实现的。并非经过get/set方法。在实体类中不管是否认义get/set()方法,都是能够接收到的。
若是面试只是考你这个点的话就恭喜了。若是继续深问流程,那就须要本身找一些源码来阅读了。
五、.mybatis分页及分页插件原理:http://blog.csdn.net/jaryle/article/details/52315565
六、.mybatis插件原理:http://blog.csdn.net/hupanfeng/article/details/9247379
七、.mybatis动态sql原理:http://www.importnew.com/24160.html
八、.mybatis延迟加载:http://blog.csdn.net/eson_15/article/details/51668523
九、Mybatis如何找到指定的Mapper的,如何完成查询的。
Dubbo
1.什么是rcp框架:http://www.javashuo.com/article/p-hpqomuon-ge.html
2.序列化方式方式及做用:http://blog.csdn.net/u012554102/article/details/51902697
3.dubbo底层协议实现:http://www.javashuo.com/article/p-kfsehtfq-gt.html
4.dubbo注册中心如何设置:http://blog.csdn.net/u011659172/article/details/51491518
5.dubbo负载均衡的理解:http://www.javashuo.com/article/p-knztwfmj-gp.html
6.dubbo容错机制:https://www.2cto.com/kf/201612/572681.html
7.服务调用超时的实现原理:http://www.javashuo.com/article/p-vasdlwnk-mv.html
8.服务注册与发现的流程:http://doc.okbase.net/661116/archive/241946.html
微服务篇
微服务
一、先后端分离是如何作的
二、微服务哪些框架
三、你怎么理解 RPC 框架
四、说说 RPC 的实现原理
五、说说 Dubbo 的实现原理
六、你怎么理解 RESTful
七、说说如何设计一个良好的 API
八、如何理解 RESTful API 的幂等性
九、如何保证接口的幂等性
十、说说 CAP 定理、 BASE 理论
十一、怎么考虑数据一致性问题
十二、说说最终一致性的实现方案
1三、你怎么看待微服务
1四、微服务与 SOA 的区别
1五、如何拆分服务
1六、微服务如何进行数据库管理
1七、如何应对微服务的链式调用异常:调用链路跟踪,全链路日志
1八、对于快速追踪与定位问题
1九、微服务的安全
分布式
一、谈谈业务中使用分布式的场景
二、Session 分布式方案
三、分布式锁的场景
四、分布是锁的实现方案
五、分布式事务
六、集群与负载均衡的算法与实现
七、说说分库与分表设计
八、分库与分表带来的分布式困境与应对之策
一致性哈希:
Memcahed缓存:
十、
分布式Session框架
十一、zookeeper是什么;
十二、zookeeper哪里用到;
1三、zookeeper的选主过程;:zab协议
1四、zookeeper集群之间如何通信;
1五、大家的zookeeper的节点加密是用的什么方式;
1六、分布式锁的实现过程;
1七、Dubbo的底层实现原理和机制
1八、描述一个服务从发布到被消费的详细过程
1九、分布式系统怎么作服务治理
20、接口的幂等性的概念
2一、消息中间件如何解决消息丢失问题
2二、Dubbo的服务请求失败怎么处理
2三、重连机制会不会形成错误
2四、对分布式事务的理解
2五、如何实现负载均衡,有哪些算法能够实现?
2六、Zookeeper的用途,选举的原理是什么?
2七、数据的垂直拆分水平拆分。
2八、zookeeper原理和适用场景
2九、zookeeper watch机制
30、redis/zk节点宕机如何处理
3一、分布式集群下如何作到惟一序列号
3三、用过哪些MQ,怎么用的,和其余mq比较有什么优缺点,MQ的链接是线程安全的吗
3四、MQ系统的数据如何保证不丢失
3五、列举出你能想到的数据库分库分表策略;分库分表后,如何解决全表查询的问题
3六、zookeeper的选举策略
3七、全局ID
3八、分布式事务的控制。
3九、分布式锁如何设计。
40、分布式session如何设计。
4一、dubbo的组件有哪些,各有什么做用。
4二、zookeeper的负载均衡算法有哪些。
4三、dubbo是如何利用接口就能够通讯的。
4四、集群环境中,session如何实现共享
答:
二、session多服务器共享方案,还有一种方案就是使用一个固定的服务器专门保持session,其余服务器共享
4五、分布式、集群环境中,缓存如何刷新,如何保持同步?
答:
A、缓存如何刷新? 一、定时刷新 二、主动刷新覆盖 ,每一个缓存框架都有自带的刷新机制,或者说缓存失效机制,就拿Redis和 Ehcache举例, 他们都有自带的过时机制,另外主动刷新覆盖时,只需获取对应的key进行数据的覆盖便可
B、缓存如何保持同步? 这个redis有自带的集群同步机制,即复制功能,具体参考:基于Redis分布式缓存实现 ,Ehcache也有分布式缓存同步的配置,只须要配置不一样服务器地址便可,参照:Ehcache分布式缓存同步
4七、Redis实现消息队列
答:Redis实现消息队列 、参考2
4八、谈谈你对分布式的理解
答:我的理解:分布式就是把一个系统/业务 拆分红多个子系统/子业务 去协同处理,这个过程就叫分布式,具体的演变方式参考:Java分布式应用技术架构介绍
安全&性能
安全问题
一、安全要素与 STRIDE 威胁
二、防范常见的 Web 攻击
三、服务端通讯安全攻防
四、HTTPS 原理剖析
六、受权与认证
七、基于角色的访问控制
八、基于数据的访问控制
性能优化
一、性能指标有哪些
二、如何发现性能瓶颈
三、性能调优的常见手段
四、说说你在项目中如何进行性能调优
解答:这个我整理过一次,web项目性能优化(整理)
六、平常项目中,若是你接手,你准备从哪些方面调优?
答:这个呢首先是了解哪些须要优化,须要优化确定是项目性能遭遇瓶颈或者猜想即将遭遇了,咱们才会去考虑优化。那么怎么优化?
a、扩容 ,扩容的理解,就是扩充服务器并行处理的能力,简单来讲就是加服务器,增长处理请求的能力,例如增长nginx 、tomcat等应用服务器的个数,或者物理服务器的个数,还有加大服务器带宽等等,这里考虑的是硬件方面
b、调优 ,调优,包括系统调优和代码调优 。 系统调优就是说加快处理速度,好比咱们所提到的CDN、ehcache、redis等缓存技术,消息队列等等,加快服务间的响应速度,增长系统吞吐量,避免并发,至于代码调优,这些就须要多积累了,好比重构、工厂等, 数据库调优的话这个我不是很懂,只知道索引和存储过程,具体参考:Mysql数据库调优21个最佳实践 ,其余数据库调优方面就各位本身找找吧
工程篇
需求分析
一、你如何对需求原型进行理解和拆分
二、说说你对功能性需求的理解
三、说说你对非功能性需求的理解
四、你针对产品提出哪些交互和改进意见
五、你如何理解用户痛点
设计能力
一、说说你在项目中使用过的 UML 图
二、你如何考虑组件化
三、你如何考虑服务化
四、你如何进行领域建模
五、你如何划分领域边界
六、说说你项目中的领域建模
七、说说概要设计
设计模式
一、你项目中有使用哪些设计模式
二、说说经常使用开源框架中设计模式使用分析
三、说说你对设计原则的理解
四、23种设计模式的设计理念
五、设计模式之间的异同,例如策略模式与状态模式的区别
六、设计模式之间的结合,例如策略模式+简单工厂模式的实践
七、设计模式的性能,例如单例模式哪一种性能更好。
业务工程
一、你系统中的先后端分离是如何作的
二、说说你的开发流程
三、你和团队是如何沟通的
四、你如何进行代码评审
五、说说你对技术与业务的理解
六、说说你在项目中常常遇到的 Exception
七、说说你在项目中遇到感受最难Bug,怎么解决的
八、说说你在项目中遇到印象最深困难,怎么解决的
九、你以为大家项目还有哪些不足的地方
十、你是否遇到过 CPU 100% ,如何排查与解决
十一、你是否遇到过 内存 OOM ,如何排查与解决
十二、说说你对敏捷开发的实践
1三、说说你对开发运维的实践
1四、介绍下工做中的一个对本身最有价值的项目,以及在这个过程当中的角色
1五、重构过代码没有?说说经验;
1六、一千万的用户实时排名如何实现;:流式计算
1七、五万人并发抢票怎么实现;:页面静态话+cdn,限流,缓存预热,读写分离,分库分表。。。
1八、大型网站应用之海量数据解决方案
http://blog.csdn.net/zhaojw_420/article/details/70881230
1九、大型网站应用之高并发状况下的解决方案
http://blog.csdn.net/zhaojw_420/article/details/70881266
20、在一个千万级的数据库查寻中,如何提升查询效率? :分库分表,读写分离,创建索引
http://blog.csdn.net/zhaojw_420/article/details/69367682
A:哈哈哈,咱们来写段代码吧……
wait()
和notify()
都是线程间通讯的方法,能够直接对线程的行为进行操做。他们的本质实际上是传递生产者-消费者各自的消息,理解了这一点,那么在分布式环境下就很简单了,只要找到一个第三方的能够用来传递消息的媒介(Zookeeper、Redis、Kafka等)就能够了。
A:能够参考Java线程池的理论与实践
若是对JDK的线程池java.util.concurrent.ThreadPoolExecutor
比较了解,能够把一些简单的特性放上去。若是不了解,能够直接设计一个线程数组,而后加一些业务逻辑。所谓线程池,基本也就如此。
A:用反射,注解,还有IOC的理论
2五、
手机扫二维码登陆是怎么实现的?
参考:http://www.jianshu.com/p/7f072ac61763
2六、
如何保证RESTful API安全性 ?
参考: http://blog.csdn.net/ywk253100/article/details/25654101
面试还会问到一些关于设计方案相关的问题,好比
3一、你的接口服务数据被人截包了,你如何防止数据恶意提交?
答:咱们能够在接口传输参数里面设置一个业务编号,这个编号用来区分是否重复提交。这样即便数据被抓包了,对方也没法区分每一个字段你的含义,这时,这个业务编号的做用就来了
3二、假设服务器常常宕机,你从哪些方面去排查问题?
答:先重启,并开启jvm输出gc日志||看是否是系统问题,若是不是则看是否是jvm问题,在看是否是oom,sof等
软实力
一、说说你的亮点
二、说说你最近在看什么书
三、说说你以为最有意义的技术书籍
四、工做之余作什么事情
五、说说我的发展方向方面的思考
六、说说你认为的服务端开发工程师应该具有哪些能力
七、说说你认为的架构师是什么样的,架构师主要作什么
八、说说你所理解的技术专家