面试题
一、Java基础
1、JDK 和 JRE 有什么区别?
JDK(Java Development Kit),Java开发工具包
JRE(Java Runtime Environment),Java运行环境
JDK中包含JRE,JDK中有一个名为jre的目录,里面包含两个文件夹bin和lib,bin就是JVM,lib就是JVM工作所需要的类库。
2、== 和 equals 的区别是什么?
对于基本类型,==比较的是值;
对于引用类型,==比较的是地址指针;
equals不能用于基本类型的比较;
如果没有重写equals,equals就相当于==;
public boolean equals(Object obj) { return (this == obj); }
如果重写了equals方法,equals比较的是对象的内容;
3、两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?
1、如果两个对象equals相等,那么这两个对象的HashCode一定也相同
2、如果两个对象的HashCode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中哈希值相等,存放于同一个位置,两个类的属性不一定相等
4、final 在 java 中有什么作用?
(1)用来修饰一个属性
1.如果引用为基本数据类型,则该引用为常量,该值无法修改; 2.如果引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,但指向该对象或数组的地址的 引用不能修改。 3.如果引用为类的成员变量,则必须当场赋值,否则编译会报错。 ***如果加在静态变量前,在编译成class文件是就带上值,在类加载的加载-链接-初始化的链接的验证-准备-解析的准备阶段显性赋值,静态变量存在堆中
(2)用来修饰一个方法
当使用final修饰方法时,这个方法将成为最终方法,无法被子类重写。但是,该方法仍然可以被继承。
(3)用来修饰类
当用final修改类时,该类成为最终类,无法被继承。 比如常用的String类就是最终类。
5、java 中的 Math.round(-1.5) 等于多少?
等于-1,四舍五入负的往大取为-1
Math提供了三个与取整有关的方法:ceil、floor、round
(1)ceil:向大取整;
Math.ceil(11.3) = 12;
Math.ceil(-11.3) = -11;
(2)floor:向小取整;
Math.floor(11.3) = 11;
Math.floor(-11.3) = -12;
(3)round:四舍五入(4往小5往大);
Math.round(11.3) = 11;
Math.round(11.8) = 12;
Math.round(-11.3) = -12;
Math.round(-11.8) = -11;
6、String 属于基础的数据类型吗?
String 不属于基础类型,基础类型有 8 种:byte、boolean(不/练)、char、short(射特)、int、float(夫肉特)、long(浪)、double,而 String 属于对象。
String在底层是以char[]或byte类型[]存储,因为char数组占两个字节(16位)而拉丁字符只需要一个字节浪费一个直接,jdk9换成了,当为拉丁字符时为byte数组,汉字时为char数组
7、java 中操作字符串都有哪些类?它们之间有什么区别?
1.操作字符串的类有:String、StringBuffer、StringBuilder。
2.String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作(缓冲区容量16,超出时扩容),所以在经常改变字符串内容的情况下最好不要使用 String。
3.StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。
8、String str="i"与 String str=new String(“i”)一样吗?
String str="i"赋值字面量时,指向字符串常量池中的地址
String str=new String(“i”),指向堆内的地址
9、如何将字符串反转?
使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。
10、String 类的常用方法都有那些?
- indexOf():返回指定字符的索引。
- charAt():返回指定索引处的字符。
- replace():字符串替换。
- trim():去除字符串两端空白。
- split():分割字符串,返回一个分割后的字符串数组。
- getBytes():返回字符串的 byte 类型数组。
- length():返回字符串长度。
- toLowerCase():将字符串转成小写字母。
- toUpperCase():将字符串转成大写字符。
- substring():截取字符串。
- equals():字符串比较。
11、抽象类必须要有抽象方法吗?
不需要,抽象类不一定非要有抽象方法
12、普通类和抽象类有哪些区别?
抽象类中可以有普通方法,但是有抽象方法的类必须是抽象类。
抽象类中的普通方法因为类不能被创建对象,所以不能使用这个普通方法
抽象类的子类必须实现抽象类中的所有抽象方法,否则子类仍然是抽象类;
抽象方法不能声明为静态、不能被static、final修饰(但是普通方法可以)。
13、抽象类能使用 final 修饰吗?
不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类
14、接口和抽象类有什么区别?
- 都不能实例化
- 实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。
- 构造函数:抽象类可以有构造函数;接口不能有。
- main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。
- 实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
- 访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。
- 方法:接口可以有抽象方法和非抽象方法,接口全是抽象方法,在jdk8之后,接口中可以定义静态方法,静态方法必须有方法体,还有default默认方法
15、java 中 IO 流分为几种?
(1)按流划分,可以分为输入流和输出流;
(2)按单位划分,可以分为字节流和字符流;
字节流:inputStream、outputStream;
字符流:reader、writer;
16、BIO、NIO、AIO 有什么区别?
- BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
- NIO:New IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
- AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。
17、Files的常用方法都有哪些?
- Files.exists():检测文件路径是否存在。
- Files.createFile():创建文件。
- Files.createDirectory():创建文件夹。
- Files.delete():删除一个文件或目录。
- Files.copy():复制文件。
- Files.move():移动文件。
- Files.size():查看文件个数。
- Files.read():读取文件。
- Files.write():写入文件。
二、反射
18、什么是反射?
所谓反射,是java在运行时进行自我观察的能力,通过class、constructor、field、method四个方法获取一个类的各个组成部分。
在Java运行时环境中,对任意一个类,可以知道类有哪些属性和方法。这种动态获取类的信息以及动态调用对象的方法的功能来自于反射机制。
在jvm加载完字节码文件之后,把字节码的数据结构(类模板)存入到方法区,并且在堆中创建一个Class的类的模板对象,在new类时,在堆中创建类对象然后指向Class类模板
19、什么是 java 序列化?什么情况下需要序列化?
序列化就是一种用来处理对象流的机制。将对象的内容流化,将流化后的对象传输于网络之间。
序列化是通过实现serializable接口,该接口没有需要实现的方法,implement Serializable只是为了标注该对象是可被序列化的,使用一个输出流(FileOutputStream)来构造一个ObjectOutputStream对象,接着使用ObjectOutputStream对象的writeObejct(Object object)方法就可以将参数的obj对象到磁盘,需要恢复的时候使用输入流。
序列化是将对象转换为容易传输的格式的过程。
例如,可以序列化一个对象,然后通过HTTP通过Internet在客户端和服务器之间传输该对象。在另一端,反序列化将从流中心构造成对象。
一般程序在运行时,产生对象,这些对象随着程序的停止而消失,但我们想将某些对象保存下来,这时,我们就可以通过序列化将对象保存在磁盘,需要使用的时候通过反序列化获取到。
对象序列化的最主要目的就是传递和保存对象,保存对象的完整性和可传递性。
譬如通过网络传输或者把一个对象保存成本地一个文件的时候,需要使用序列化。
****序列化就是把对象流化,方便与对象的传输,保存;对象通过实现序列化接口,这个接口没有需要实现的方法,只是为了标志这个对象可以序列化 ; 通过输出流就可以把对象保存带磁盘中,使用时在用输入流反序列化出对象,反序列化并不会调用构造方法。反序列的对象是由 JVM 自己生成的对象,不通过构造方法生成;
20、动态代理是什么?有哪些应用?
动态代理:
当想要给实现了某个接口的类中的方法,加一些额外的处理。比如说加日志,加事务等。
动态代理的应用:
- Spring的AOP
- 加事务
- 加权限
- 加日志
21、怎么实现动态代理?
首先必须定义一个接口,和实现接口的被代理类
实现InvocationHandler接口的代理类
在代理类中创建方法返回 Proxy.newProxyInstance(普唠嗑系.牛 普唠嗑系 音死腾死)代理.新建代理实例 生成的被代理对象实例
参数说明
第一个参数 本类(代理类)的类加载器
第二个参数 被代理类实现的所有接口
第三个参数 本类(代理类)
在本类中的中invoke方法插入增加的代码
三、对象拷贝
22、为什么要使用克隆?
想对一个对象进行复制,又想保留原有的对象进行接下来的操作,如读写分离,拷贝一份用来写,一份用来读
23、如何实现对象克隆?
实现Cloneable(克隆)接口,重写clone(克隆)方法;
实现Serializable接口(序列化接口),通过对象的序列化和反序列化实现克隆,可以实现真正的深克隆,为保证引用类型属性也能序列化,所以引用类型属性也必须实现序列 化接口。
BeanUtils,apache和Spring都提供了bean工具,只是这都是浅克隆。
24、深拷贝和浅拷贝区别是什么?
浅拷贝:仅仅克隆基本类型变量,不克隆引用类型变量,引用类型赋值指针地址;
深拷贝:既克隆基本类型变量,又克隆引用类型变量,重写克隆方法,或者序列化不过得保证引用类型也要继承序列化接口;
四、异常
25、throw 和 throws 的区别?
- 作用不同:throw用于在程序中抛出异常,throws用于声明在该方法内抛出了异常。
- 使用位置不同:throw位于方法体内部,可以作为单独语句是用,throws必须跟在方法参数列表后面,不能单独使用。
- 内容不同:throw抛出一个异常对象,而且只能是一个,throws后面跟异常类,可以有多个。
26、final、finally、finalize 有什么区别?
final(fai柔):是修饰符,修饰类,变量,方法,修饰的类不能被继承,修饰的变量不能重新赋值,修饰的方法不能被重写
finally(fail柔里):是 try{} catch{} finally{} 最后一部分,表示不论发生任何情况都会执行,finally 部分可以省略,但如果 finally 部分存在,则一定会执行 finally 里面的代码。
finalize fai柔赖死(终结器方法):是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法。
27、try-catch-finally 中哪个部分可以省略?
try-catch-finally 其中 catch 和 finally 都可以被省略,但是不能同时省略,也就是说有 try 的时候,必须后面跟一个 catch 或者 finally。
28、try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?
catch -》finally -》catch return
29、常见的异常类有哪些?
NullPointerException 空指针异常
ClassNotFoundException 指定类不存在
NumberFormatException 字符串转换为数字异常
IndexOutOfBoundsException 数组下标越界异常
ClassCastException 数据类型转换异常
FileNotFoundException 文件未找到异常
NoSuchMethodException 方法不存在异常
IOException IO 异常
SocketException Socket 异常oom 内存异常,sof 栈溢出,多线程异常
30、new String("a") + new String("b") 会创建几个对象?
- 对象1:new StringBuilder()
- 对象2: new String(“a”)
- 对象3: 常量池中的"a"
- 对象4: new String(“b”)
- 对象5: 常量池中的"b"
- 对象6 :new String(“ab”)
强调一下,toString()的调用,在字符串常量池中,没有生成"ab"
五、Java集合
1、java 容器都有哪些?
Collection 磕来磕旋
- list 可重复
-- arraylist
- - - 数组 object[]
- - linkedlist
- - - 链表node[E] new node <>(null,e,f),e数据 f节点指针
- - vector 歪磕特
- - - 线程安全,方法加了synchronize (先扣乃斯)
- set 不可重复
- - hashset
- - - 不排序的 底层是hashmap (e,object)计算对象e的hash值
- - treeset
- - - 排序的,二叉树
- map
- - hashmap
- - - 散列存放 数组+链表+红黑树 底层node <E,V>[] node <>{hashcode,e,v,f} hashcode哈希值,e key值,v value值,f新节点指针;在jdk7头插法,8尾插法;当同一个位置的节点大于8,链
表转为红黑树
- - - linkedhashmap
- - - - 顺序存放 在hashmap基础上+双向链表,把所有节点按顺序存入双向链表
- -hashtable
- - - 与hashmap区别同步操作,线程安全,不保存null数据
- - treemap
- - -排序的,结点, 红黑树,红黑树是一棵平衡排序二叉树
2、Collection 和 Collections 有什么区别?
java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。
Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作
3、List、Set、Map 之间的区别是什么?
元素重复:List元素重复;set,map不重复,map中key唯一,value可重复
元素有序:list有序;set无序,但treeset用二叉树排序,map无序,treemap有序
4、HashMap 和 Hashtable 有什么区别?
存储:HashMap 运行 key 和 value 为 null,而 Hashtable 不允许。
线程安全:Hashtable 是线程安全的,而 HashMap 是非线程安全的。
推荐使用:在 Hashtable 的类注释可以看到,Hashtable 是保留类不建议使用,推荐在单线程环境下使用 HashMap 替代,如果需要多线程使用则用 ConcurrentHashMap 并发的hashmap替代。
5、说一下 HashMap 的实现原理?
7采用数组加链表的存储结构,8以后数组+链表或红黑树
底层是node[]数组,有4个重要属性hash哈希值、key、value、next下一个结点指针
通过计算对象实现的计算哈希值方法得到的哈希值,通过哈希值放到对应数组位置,再通过 equals方法判断key是否相等,相等就替换,不相等就添加,7头插法·8尾插法七上八下,链表大于8时,转为红黑树
6、set有哪些实现类?
(1)HashSet
HashSet是set接口的实现类,set下面最主要的实现类就是HashSet(也就是用的最多的),此外还有LinkedHashSet和TreeSet。
HashSet是无序的、不可重复的。通过对象的hashCode和equals方法保证对象的唯一性。
HashSet内部的存储结构是哈希表,是线程不安全的。(2)TreeSet
TreeSet对元素进行排序的方式:
元素自身具备比较功能,需要实现Comparable接口,并覆盖compareTo方法。
元素自身不具备比较功能,需要实现Comparator接口,并覆盖compare方法。(3)LinkedHashSet
LinkedHashSet是一种有序的Set集合,即其元素的存入和输出的顺序是相同的。
7、说一下 HashSet 的实现原理?
HashSet是基于HashMap实现的,HashSet中的元素都存放在HashMap的key上面,而value都是一个统一的对象PRESENT。
HashSet中add方法调用的是底层HashMap中的put方法,put方法要判断插入值是否存在,而HashSet的add方法,首先判断元素是否存在,如果存在则插入,如果不存在则不插入,这样就保证了HashSet中不存在重复值
8、ArrayList 和 LinkedList 的区别是什么?
ArrayList是动态数组的数据结构实现,查找和遍历的效率较高;
LinkedList 是双向链表的数据结构,增加和删除的效率较高;
9、如何实现数组和 List 之间的转换?
- List转换成为数组:调用ArrayList的toArray方法。
- 数组转换成为List:调用Arrays的asList方法。
10、ArrayList 和 Vector 的区别是什么?
- 线程安全:Vector 使用了 Synchronized 来实现线程同步,是线程安全的,而 ArrayList 是非线程安全的。
- 性能:ArrayList 在性能方面要优于 Vector。
- 扩容:ArrayList 和 Vector 都会根据实际的需要动态的调整容量,只不过在 Vector 扩容每次会增加 1 倍,而 ArrayList 只会增加 50%。
11、Array(数组)和 ArrayList 有何区别?
- Array可以容纳基本类型和对象,而ArrayList只能容纳对象。
- Array是指定大小的,而 ArrayList 大小是自动扩展的
- Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。
12、在 Queue 中 poll()和 remove()有什么区别?
相同点:都是返回第一个元素,并在队列中删除返回的对象。
不同点:如果没有元素 poll()会返回 null,而 remove()会直接抛出 NoSuchElementException 异常
13、哪些集合类是线程安全的?
- vector:就比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。
- statck:堆栈类,先进后出。
- hashtable:就比hashmap多了个线程安全。
- enumeration:枚举,相当于迭代器。
14、迭代器 Iterator 是什么?
迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。
Iterator 接口提供遍历任何 Collection 的接口。我们可以从一个 Collection 中使用迭代器方法来获取迭代器实例。迭代器取代了 Java 集合框架中的 Enumeration,迭代器允许调用者在迭代过程中移除元素。
数组有序可以用下标或者迭代器遍历,无序的set无法用下标遍历
15、Iterator (衣德瑞德)怎么使用?有什么特点?
集合对象调用迭代器方法返回迭代器对象,循环判断迭代器是否未空,方法体内获取迭代器元素
Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。
(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()呐克斯特方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
(2) 使用next()获得序列中的下一个元素。
(3) 使用hasNext()害死呐科特检查序列中是否还有元素。
List<String> list = new ArrayList<>();
Iterator<String> it = list. iterator();
while(it. hasNext()){
String obj = it. next();
System. out. println(obj);
}
16、Iterator 和 ListIterator 有什么区别?
Iterator 可以遍历 Set 和 List 集合,而 ListIterator 只能遍历 List。
Iterator 只能单向遍历,而 ListIterator 可以双向遍历(向前/后遍历)。
ListIterator 从 Iterator 接口继承,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。
17、怎么确保一个集合不能被修改?
可以使用 Collections. unmodifiableCollection(Collection c) 方法来创建一个只读集合,这样改变集合的任何操作都会抛出 Java. lang. UnsupportedOperationException 异常。
**用集合工具类创建只读集合
18、队列和栈是什么?有什么区别?
(1)队列先进先出,栈先进后出。
(2)遍历数据速度不同。
栈只能从头部取数据 也就最先放入的需要遍历整个栈最后才能取出来,而且在遍历数据的时候还得为数据开辟临时空间,保持数据在遍历前的一致性;
队列则不同,他基于地址指针进行遍历,而且可以从头或尾部开始遍历,但不能同时遍历,无需开辟临时空间,因为在遍历的过程中不影响数据结构,速度要快的多。
三、多线程
1、Synchronized 用过吗,其原理是什么?
(1)可重入性
synchronized的锁对象中有一个计数器(recursions变量)会记录线程获得几次锁;
可重入的好处: 可以避免死锁; 可以让我们更好的封装代码;
synchronized是可重入锁,每部锁对象会有一个计数器记录线程获取几次锁,在执行完同步代码块时,计数器的数量会-1,直到计数器的数量为0,就释放这个锁。
(2)不可中断性
一个线程获得锁后,另一个线程想要获得锁,必须处于阻塞或等待状态,如果第一个线程不释放锁,第二个线程会一直阻塞或等待,不可被中断; synchronized 属于不可被中断; Lock lock方法是不可中断的; Lock tryLock方法是可中断的;
Synchronized锁的是对象(锁对象中加锁的方法),有不可重入和不可中断性,原理是在每个锁对象都有一个计数器,当线程获取对象的时候就会加一,当执行完同步代码块时就减一,当为0时就释放对象锁
2、请对比下 volatile 对比 Synchronized 新亏耐斯特 的异同。
volatile 是变量修饰符;synchronized 是修饰类、方法、代码段。
volatile 仅能实现变量的修改可见性,不能保证原子性;而 synchronized 则可以保证变量的修改可见性和原子性。
volatile 不会造成线程的阻塞;synchronized 可能会造成线程的阻塞。volatile :修饰变量,一个线程变量修改时立即回显到主内存中,保证所有线程看到最新变量
3、请谈谈 volatile 有什么特点,为什么它能保证变量对所有线程的可见性?
一个线程变量修改时立即回显到主内存中,保证所有线程看到最新变量
volatile 的一个重要作用就是和 CAS 结合,保证了原子性
volatile修饰的变量在各个线程的工作内存中不存在一致性的问题(在各个线程工作的内存中,volatile修饰的变量也会存在不一致的情况,但是由于每次使用之前都会先刷新主存中的数据到工作内存,执行引擎看不到不一致的情况,因此可以认为不存在不一致的问题),但是java的运算并非原子性的操作,导致volatile在并发下并非是线程安全的。
4、JVM 对 Java 的原生锁做了哪些优化?
自旋锁、自适应自旋锁、锁粗化、锁消除、偏向锁、轻量级锁、重量级锁
(1)自旋锁
在线程进行阻塞的时候,先让线程自旋等待一段时间,可能这段时间其它线程已经解锁,这时就无需让线程再进行阻塞操作了。
自旋默认次数是10次。
(2)自适应自旋锁
自旋锁的升级,自旋的次数不再固定,由前一次自旋次数和锁的拥有者的状态决定。如果前面线程成功获取锁并且正常运行,那么本次获取锁的可能性很大,所以自旋的次数相对多一些;如果前面线程很少成功获取锁,那么本次获取锁的概率也很小,就可能不执行自旋了。
(3)锁消除
在动态编译同步代码块的时候,JIT编译器借助逃逸分析技术来判断锁对象是否只被一个线程访问,而没有其他线程,这时就可以取消锁了。
(4)、锁粗化
当JIT编译器发现在一段代码中同一线程反复获取、释放同一个对象的锁,将会生产不必要的性能开销,所以需要把获锁的范围扩大,对同一个对象的锁操作只进行一次,在头部获取锁,在尾部释放锁,例如在一个循环中循环获取释放锁,就扩大范围在循环前获得锁,结束释放锁。
(5)、偏向锁
偏向锁就是如果线程持有了锁,在后续的过程中,只要该锁没有被其它线程持有,那么持有偏向锁的线程将不再需要进行同步操作
(6)轻量级锁、重量级锁
当没有竞争出现时,默认会使用偏向锁。
JVM会利用CAS操作,在对象头上的Mark Word部分设置线程ID,以表示这个对象偏向于当前线程,所以并不涉及真正的互斥锁,因为在很多应用场景中,大部分对象生命周期中最多会被一个线程锁定,使用偏斜锁可以降低无竞争开销。
·如果有另一线程试图锁定某个被偏斜过的对象,JM就撤销偏斜锁,切换到轻量级锁实现。
·轻量级锁依赖CAS操作Mark Word来试图获取锁,如果重试成功,就使用普通的轻量级锁;否则,进一步升级为重量级锁。
5、为什么说 Synchronized 是非公平锁?
因为 Synchronized 获取锁的行为是不公平的,并非是按照申请对象锁的先后时间分配锁的,每次对象锁被释放时,每个线程都有机会获得对象锁,这样有利于提高执行性能,但是也会造成线程饥饿现象。
6、什么是锁消除和锁粗化?
7、为什么说 Synchronized 是一个悲观锁?乐观锁的实现原理又是什么?什么是 CAS,它有什么特性?
Synchronized 显然是一个悲观锁,因为它的并发策略是悲观的: 不管是否会产生竞争,任何的数据操作都必须要加锁、用户态核心态转换、维护锁计数器和检查是否有被阻塞的线程需要被唤醒等操作。
乐观锁,对于共享的数据多个线程先操作无需线程挂起,进行非阻塞同步,基于cas来判断是否发送冲突,发送冲突在进行其他补偿措施
观锁的核心算法是 CAS(Compareand Swap,比较并交换),它涉及到三个操作数:内存值、预期值、新值。当且仅当预期值和内存值相等时才将内存值修改为新值。 这样处理的逻辑是,首先检查某块内存的值是否跟之前我读取时的一样,如不一样则表示期间此内存值已经被别的线程更改过,舍弃本次操作,否则说明期间没有其他线程对此内存值操作,可以把新值设置给此块内存。 CAS 具有原子性
就像淘宝买东西,这个衣服100块加入购物车,你在逛一会淘宝,最后清空购物车,看看100块的衣服价格有没有变进行对比,变了就不要了
8、乐观锁一定就是好的吗?
乐观锁避免了悲观锁独占对象的现象,同时也提高了并发性能,但它也有缺点:
- 乐观锁只能保证一个共享变量的原子操作。如果多一个或几个变量,乐观锁将变得力不从心,但互斥锁能轻易解决,不管对象数量多少及对象颗粒度大小。
- 长时间自旋可能导致开销大。假如 CAS 长时间不成功而一直自旋,会给 CPU 带来很大的开销。
- ABA 问题。CAS 的核心思想是通过比对内存值与预期值是否一样而判断内存值是否被改过,但这个判断逻辑不严谨,假如内存值原来是 A,后来被一条线程改为 B,最后又被改成了 A,则 CAS 认为此内存值并没有发生改变,但实际上是有被其他线程改过的,这种情况对依赖过程值的情景的运算结果影响很大。解决的思路是引入版本号,每次变量更新都把版本号加一。
9、跟 Synchronized 相比,可重入锁 ReentrantLock 其实现原理有什么不同?
synchronized 属于独占式悲观锁,是通过 JVM 隐式实现的,synchronized 只允许同一时刻只有一个线程操作资源。
在 Java 中每个对象都隐式包含一个 monitor(监视器)对象,加锁的过程其实就是竞争 monitor 的过程,当线程进入字节码 monitorenter 指令之后,线程将持有 monitor 对象,执行 monitorexit 时释放 monitor 对象,当其他线程没有拿到 monitor 对象时,则需要阻塞等待获取该对象。
ReentrantLock 是 Lock 的默认实现方式之一,它是基于 AQS(Abstract Queued Synchronizer,队列同步器)实现的,它默认是通过非公平锁实现的,在它的内部有一个 state 的状态字段用于表示锁是否被占用,如果是 0 则表示锁未被占用,此时线程就可以把 state 改为 1,并成功获得锁,而其他未获得锁的线程只能去排队等待获取锁资源。
synchronized 和 ReentrantLock 都提供了锁的功能,具备互斥性和不可见性。在 JDK 1.5 中 synchronized 的性能远远低于 ReentrantLock,但在 JDK 1.6 之后 synchronized 的性能略低于 ReentrantLock,它的区别如下:
synchronized 是 JVM 隐式实现的,而 ReentrantLock 是 Java 语言提供的 API;
ReentrantLock 可设置为公平锁,而 synchronized 却不行;
ReentrantLock 只能修饰代码块,而 synchronized 可以用于修饰方法、修饰代码块等;
ReentrantLock 需要手动加锁和释放锁,如果忘记释放锁,则会造成资源被永久占用,而 synchronized 无需手动释放锁;
ReentrantLock 可以知道是否成功获得了锁,而 synchronized 却不行。
10、那么请谈谈 AQS 框架是怎么回事儿?
- AQS是⼀个JAVA线程同步的框架。是JDK中很多锁⼯具的核⼼实现框架。
- 在AQS中,维护了⼀个信号量state和⼀个线程组成的双向链表队列。其中,这个线程队列,就是⽤
来给线程排队的,⽽state就像是⼀个红绿灯,⽤来控制线程排队或者放⾏的。 在不同的场景下,
有不⽤的意义。- 在可重⼊锁这个场景下,state就⽤来表示加锁的次数。0标识⽆锁,每加⼀次锁,state就加1。释
放锁state就减1。
11、请尽可能详尽地对比下 Synchronized 和 ReentrantLock 的异同。
synchronized 是 JVM 隐式实现的,而 ReentrantLock 是 Java 语言提供的 API;
ReentrantLock 可设置为公平锁,而 synchronized 却不行;
ReentrantLock 只能修饰代码块,而 synchronized 可以用于修饰方法、修饰代码块等;
ReentrantLock 需要手动加锁和释放锁,如果忘记释放锁,则会造成资源被永久占用,而 synchronized 无需手动释放锁;
ReentrantLock 可以知道是否成功获得了锁,而 synchronized 却不行。
12、ReentrantLock 是如何实现可重入性的?
ReentrantLock使用内部类Sync来管理锁,所以真正的获取锁是由Sync的实现类控制的。Sync有两个实现,分别为NonfairSync(非公公平锁)和FairSync(公平锁)。Sync通过继承AQS实现,在AQS中维护了一个private volatile int state来计算重入次数,避免频繁的持有释放操作带来的线程问题。
13、除了 ReetrantLock,你还接触过 JUC 中的哪些并发工具?
14、请谈谈 ReadWriteLock 和 StampedLock。
15、如何让 Java 的线程彼此同步?你了解过哪些同步器?请分别介绍下。
16、CyclicBarrier 和 CountDownLatch 看起来很相似,请对比下呢?
17、Java 线程池相关问题
18、Java 中的线程池是如何实现的?
19、创建线程池的几个核心构造参数?
20、线程池中的线程是怎么创建的?是一开始就随着线程池的启动创建好的吗?
21、既然提到可以通过配置不同参数创建出不同的线程池,那么 Java 中默认实现好的线程池又有哪些呢?请比较它们的异同
22、如何在 Java 线程池中提交线程?
23、什么是 Java 的内存模型,Java 中各个线程是怎么彼此看到对方的变量的?
24、ThreadLocal 是什么?有哪些使用场景?
25、既然 volatile 能够保证线程间的变量可见性,是不是就意味着基于 volatile 变量的运算就是并发安全的?
26、Java8开始ConcurrentHashMap,为什么舍弃分段锁?
27、请谈谈 ThreadLocal 是怎么解决并发安全的?
28、很多人都说要慎用 ThreadLocal,谈谈你的理解,使用 ThreadLocal 需要注意些什么?
29、什么是上下文切换?
30、线程的run()和start()有什么区别?
31、为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法?
32、什么是线程调度器(Thread Scheduler)和时间分片(Time Slicing )?
33、为什么 wait(), notify()和 notifyAll()必须在同步方法或者同步块中被调用?
34、Thread 类中的 yield 方法有什么作用?
35、Java 如何实现多线程之间的通讯和协作?
36、为什么代码会重排序?
37、什么是自旋
38、多线程中 synchronized 锁升级的原理是什么?
39、synchronized 和 ReentrantLock 区别是什么?
40、volatile 关键字的作用
41、Java Concurrency API 中的 Lock 接口(Lock interface)是什么?对比同步它有什么优势?
42、AQS是什么?
43、AQS 对资源的共享方式?
四、Java Web
1、jsp 和 servlet 有什么区别?
2、jsp 有哪些内置对象?作用分别是什么?
3、说一下 jsp 的 4 种作用域?
4、session 和 cookie 有什么区别?
5、说一下 session 的工作原理?
6、如果客户端禁止 cookie 能实现 session 还能用吗?
7、spring mvc 和 struts 的区别是什么?
8、如何避免 sql 注入?
9、什么是 XSS 攻击,如何避免?
10、什么是 CSRF 攻击,如何避免?
五、网络
1、http 响应码 301 和 302 代表的是什么?有什么区别?
2、forward 和 redirect 的区别?
3、简述 tcp 和 udp的区别?
4、tcp 为什么要三次握手,两次不行吗?为什么?
5、说一下 tcp 粘包是怎么产生的?
6、OSI 的七层模型都有哪些?
7、get 和 post 请求有哪些区别?
8、如何实现跨域?
9、说一下 JSONP 实现原理?
六、设计模式
1、请列举出在 JDK 中几个常用的设计模式?
2、什么是设计模式?你是否在你的代码里面使用过任何设计模式?
3、Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
4、在 Java 中,什么叫观察者设计模式(observer design pattern)?
5、使用工厂模式最主要的好处是什么?在哪里使用?
6、举一个用 Java 实现的装饰模式(decorator design pattern)?它是作用于对象层次还是类层次?
7、在 Java 中,为什么不允许从静态方法中访问非静态变量?
8、设计一个 ATM 机,请说出你的设计思路?
9、在 Java 中,什么时候用重载,什么时候用重写?
10、举例说明什么情况下会更倾向于使用抽象类而不是接口
七、Spring/SpringMVC
1、什么是 Spring 框架?Spring 框架有哪些主要模块?
2、使用 Spring 框架能带来哪些好处?
3、什么是控制反转(IOC)?什么是依赖注入?
4、请解释下 Spring 框架中的 IoC?
5、BeanFactory 和 ApplicationContext 有什么区别?
6、Spring 有几种配置方式?
7、请解释 Spring Bean 的生命周期?
8、Spring Bean 的作用域之间有什么区别?
9、什么是 Spring inner beans?
10、Spring 框架中的单例 Beans 是线程安全的么?
11、请举例说明如何在 Spring 中注入一个 Java Collection?
12、如何向 Spring Bean 中注入一个 Java.util.Properties?
13、请解释 Spring Bean 的自动装配?
14、请解释自动装配模式的区别?
15、如何开启基于注解的自动装配?
16、请举例解释@Required 注解?
17、请举例解释@Autowired 注解?
18、请举例说明@Qualifier 注解?
19、构造方法注入和设值注入有什么区别?
20、Spring 框架中有哪些不同类型的事件?
21、FileSystemResource 和 ClassPathResource 有何区别?
22、Spring 框架中都用到了哪些设计模式?
八、Spring Boot/Spring Cloud
1、什么是 Spring Boot?
2、Spring Boot 有哪些优点?
3、什么是 JavaConfig?
5、Spring Boot 中的监视器是什么?
6、如何在 Spring Boot 中禁用 Actuator 端点安全性?
7、如何在自定义端口上运行 Spring Boot 应用程序?
8、什么是 YAML?
9、如何实现 Spring Boot 应用程序的安全性?
10、如何集成 Spring Boot 和 ActiveMQ?
11、如何使用 Spring Boot 实现分页和排序?
12、什么是 Swagger?你用 Spring Boot 实现了它吗?
13、什么是 Spring Profiles?
14、什么是 Spring Batch?
15、什么是 FreeMarker 模板?
16、如何使用 Spring Boot 实现异常处理?
17、您使用了哪些 starter maven 依赖项?
18、什么是 CSRF 攻击?
19、什么是 WebSockets?
20、什么是 AOP?
21、什么是 Apache Kafka?
22、我们如何监视所有 Spring Boot 微服务?
23、什么是 spring cloud?
24、spring cloud 断路器的作用是什么?
26、spring cloud 的核心组件有哪些?
九、Hibernate
1、为什么要使用 hibernate?
2、什么是 ORM 框架?
3、hibernate 中如何在控制台查看打印的 sql 语句?
4、hibernate 有几种查询方式?
5、hibernate 实体类可以被定义为 final 吗?
6、在 hibernate 中使用 Integer 和 int 做映射有什么区别?
7、hibernate 是如何工作的?
8、get()和 load()的区别?
9、说一下 hibernate 的缓存机制?
10、hibernate 对象有哪些状态?
11、在 hibernate 中 getCurrentSession 和 openSession 的区别是什么?
12、hibernate 实体类必须要有无参构造函数吗?为什么?
十、MyBatis
1、mybatis 中 #{}和 ${}的区别是什么?
2、mybatis 有几种分页方式?
3、RowBounds 是一次性查询全部结果吗?为什么?
4、mybatis 逻辑分页和物理分页的区别是什么?
5、mybatis 是否支持延迟加载?延迟加载的原理是什么?
6、说一下 mybatis 的一级缓存和二级缓存?
7、mybatis 和 hibernate 的区别有哪些?
8、mybatis 有哪些执行器(Executor)?
9、mybatis 分页插件的实现原理是什么?
10、mybatis 如何编写一个自定义插件?
十一、RabbitMQ
1、RabbitMQ的使用场景有哪些?
2、RabbitMQ有哪些重要的角色?
3、RabbitMQ有哪些重要的组件?
4、RabbitMQ中 vhost 的作用是什么?
5、RabbitMQ的消息是怎么发送的?
6、RabbitMQ怎么保证消息的稳定性?
7、RabbitMQ怎么避免消息丢失?
8、要保证消息持久化成功的条件有哪些?
9、RabbitMQ持久化有什么缺点?
10、RabbitMQ有几种广播类型?
11、RabbitMQ怎么实现延迟消息队列?
12、RabbitMQ集群有什么用?
13、RabbitMQ节点的类型有哪些?
14、RabbitMQ集群搭建需要注意哪些问题?
15、RabbitMQ每个节点是其他节点的完整拷贝吗?为什么?
16、RabbitMQ集群中唯一一个磁盘节点崩溃了会发生什么情况?
17、RabbitMQ对集群节点停止顺序有要求吗?
十二 、Kafka(未掌握,暂时不做)
如何获取 topic 主题的列表
生产者和消费者的命令行是什么?
consumer是推还是拉?
讲讲kafka维护消费状态跟踪的方法
讲一下主从同步
为什么需要消息系统,mysql 不能满足需求吗?
Zookeeper 对于 Kafka 的作用是什么?
数据传输的事务定义有哪三种?
Kafka 判断一个节点是否还活着有那两个条件?
Kafka 与传统 MQ 消息系统之间有三个关键区别
讲一讲 kafka 的 ack 的三种机制
消费者如何不自动提交偏移量,由应用提交?
消费者故障,出现活锁问题如何解决?
如何控制消费的位置
kafka分布式(不是单机)的情况下,如何保证消息的顺序消费?
kafka的高可用机制是什么?
kafka如何减少数据丢失
kafka如何不消费重复数据?比如扣款,我们不能重复的扣。
十三、Zookeeper(未掌握,暂时不做)
ZooKeeper 提供了什么?
Zookeeper 文件系统
ZAB 协议?
四种类型的数据节点 Znode
Zookeeper Watcher 机制 – 数据变更通知
客户端注册 Watcher 实现
服务端处理 Watcher 实现
客户端回调 Watcher
ACL 权限控制机制
Chroot 特性
会话管理
服务器角色
Zookeeper 下 Server 工作状态
数据同步
zookeeper 是如何保证事务的顺序一致性的?
分布式集群中为什么会有 Master?
zk 节点宕机如何处理?
zookeeper 负载均衡和 nginx 负载均衡区别
Zookeeper 有哪几种几种部署模式?
集群最少要几台机器,集群规则是怎样的?
集群支持动态添加机器吗?
Zookeeper 对节点的 watch监听通知是永久的吗?为什么不是永久的?
Zookeeper 的 java 客户端都有哪些?
chubby 是什么,和 zookeeper 比你怎么看?
说几个 zookeeper 常用的命令。
ZAB 和 Paxos 算法的联系与区别?
Zookeeper 的典型应用场景
十四、MySql
1、数据库的三范式是什么?
2、一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了一条数据,此时 id 是几?
3、如何获取当前数据库版本?
4、说一下 ACID 是什么?
5、char 和 varchar 的区别是什么?
6、float 和 double 的区别是什么?
7、mysql 的内连接、左连接、右连接有什么区别?
8、mysql 索引是怎么实现的?
9、怎么验证 mysql 的索引是否满足需求?
10、说一下数据库的事务隔离?
11、说一下 mysql 常用的引擎?
12、说一下 mysql 的行锁和表锁?
13、说一下乐观锁和悲观锁?
14、mysql 问题排查都有哪些手段?
15、如何做 mysql 的性能优化?
十五、Redis
1、Redis是什么?都有哪些使用场景?
2、Redis有哪些功能?
3、Redis和 memecache 有什么区别?
4、Redis为什么是单线程的?
5、什么是缓存穿透?怎么解决?
6、Redis支持的数据类型有哪些?
7、Redis支持的 java 客户端都有哪些?
8、jedis 和 redisson 有哪些区别?
9、怎么保证缓存和数据库数据的一致性?
10、Redis持久化有几种方式?
11、Redis怎么实现分布式锁?
12、Redis分布式锁有什么缺陷?
13、Redis如何做内存优化?
14、Redis淘汰策略有哪些?
15、Redis常见的性能问题有哪些?该如何解决?
十六、JVM
1、说一下 jvm 的主要组成部分?及其作用?
2、说一下 jvm 运行时数据区?
3、说一下堆栈的区别?
4、什么是类加载器,类加载器有哪些?
5、什么是双亲委派模型?
6、说一下类加载的执行过程?
7、怎么判断对象是否可以被回收?
8、java 中都有哪些引用类型?
9、说一下 jvm 有哪些垃圾回收算法?
10、说一下 jvm 有哪些垃圾回收器?
11、详细介绍一下 CMS 垃圾回收器?
12、新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?
13、简述分代垃圾回收器是怎么工作的?
14、说一下 jvm 调优的工具?
15、常用的 jvm 调优的参数都有哪些?
16、Java 类加载过程?
17、描述一下 JVM 加载 Class 文件的原理机制?
18、Java 内存分配。
19、gc 是什么? 为什么要有 gc?
20、简述 Java 垃圾回收机制
21、如何判断一个对象是否存活?(或者 gc 对象的判定方法)
22、垃圾回收的优点和原理。并考虑 2 种回收机制
23、垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?
24、Java 中会存在内存泄漏吗,请简单描述
25、深拷贝和浅拷贝。
26、System.gc() 和 Runtime.gc() 会做什么事情?
27、finalize() 方法什么时候被调用?析构函数 (finalization) 的目的是什么?
28、如果对象的引用被置为 null,垃圾收集器是否会立即释放对象占用的内存?
29、串行(serial)收集器和吞吐量(throughput)收集器的区别是什么?
30、在 Java 中,对象什么时候可以被垃圾回收?
31、简述 Java 内存分配与回收策略以及 Minor gc 和 Major gc。
32、VM 的永久代中会发生垃圾回收么?
33、Java 中垃圾收集的方法有哪些?
34、运行时常量池和字符串常量池的区别
常量池
每个class一份,存在于字节码文件中。常量池中有字面量(数量值、字符串值)和符号引用(类符号引用、字段符号引用、方法符号引用),虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等类型
运行时常量池
每个class一份,存在于方法区中(元空间)。当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中,经过解析(resolve)之后,也就是把符号引用替换为直接引用,解析的过程会去查询全局字符串池,也就是下面的StringTable,以保证运行时常量池所引用的字符串与全局字符串池中所引用的是一致的。
字符串常量池
每个JVM中只有一份,存在于方法区中(堆)。全局字符串池里的内容是在类加载完成,经过验证,准备阶段之后在堆中生成字符串对象实例,然后将该字符串对象实例的引用值存到string pool中(string pool中存的是引用值而不是具体的实例对象,具体的实例对象是在堆中开辟的一块空间存放的)。 在HotSpot VM里实现的string pool功能的是一个StringTable类,它是一个哈希表,里面存的是驻留字符串(用双引号括起来的引用而不是驻留字符串实例本身),也就是说在堆中的某些字符串实例被这个StringTable引用之后就等同被赋予了”驻留字符串”的身份。
十七、Dubbo 面试题(未掌握,暂时不做)
为什么要用 Dubbo?
Dubbo 的整体架构设计有哪些分层?
默认使用的是什么通信框架,还有别的选择吗?
服务调用是阻塞的吗?
一般使用什么注册中心?还有别的选择吗?
默认使用什么序列化框架,你知道的还有哪些?
服务提供者能实现失效踢出是什么原理?
服务上线怎么不影响旧版本?
如何解决服务调用链过长的问题?
说说核心的配置有哪些?
Dubbo 推荐用什么协议?
同一个服务多个注册的情况下可以直连某一个服务吗?
画一画服务注册与发现的流程图?
Dubbo 集群容错有几种方案?
Dubbo 服务降级,失败重试怎么做?
Dubbo 使用过程中都遇到了些什么问题?
Dubbo Monitor 实现原理?
Dubbo 用到哪些设计模式?
Dubbo 配置文件是如何加载到 Spring 中的?
Dubbo SPI 和 Java SPI 区别?
Dubbo 支持分布式事务吗?
Dubbo 可以对结果进行缓存吗?
服务上线怎么兼容旧版本?
Dubbo 必须依赖的包有哪些?
Dubbo telnet 命令能做什么?
Dubbo 支持服务降级吗?
Dubbo 如何优雅停机?
Dubbo 和 Dubbox 之间的区别?
Dubbo 和 Spring Cloud 的区别?
你还了解别的分布式框架吗?
十八、Elasticsearch 面试题(未掌握,暂时不做)
elasticsearch 了解多少,说说你们公司 es 的集群架构,索引数据大小,分片有多少,以及一些调优手段 。
elasticsearch 的倒排索引是什么
elasticsearch 索引数据多了怎么办,如何调优,部署
elasticsearch 是如何实现 master 选举的
详细描述一下 Elasticsearch 索引文档的过程
详细描述一下 Elasticsearch 搜索的过程?
Elasticsearch 在部署时,对 Linux 的设置有哪些优化方法
lucence 内部结构是什么?
Elasticsearch 是如何实现 Master 选举的?
Elasticsearch 中的节点(比如共 20 个),其中的 10 个选了一个 master,另外 10 个选了另一个 master,怎么办?
客户端在和集群连接时,如何选择特定的节点执行请求的?
详细描述一下 Elasticsearch 索引文档的过程。
详细描述一下 Elasticsearch 更新和删除文档的过程。
详细描述一下 Elasticsearch 搜索的过程
在 Elasticsearch 中,是怎么根据一个词找到对应的倒排索引的?
Elasticsearch 在部署时,对 Linux 的设置有哪些优化方法?
对于 gc 方面,在使用 Elasticsearch 时要注意什么?
Elasticsearch 对于大数据量(上亿量级)的聚合如何实现?
在并发情况下,Elasticsearch 如果保证读写一致?
如何监控 Elasticsearch 集群状态?
介绍下你们电商搜索的整体技术架构
介绍一下你们的个性化搜索方案?
是否了解字典树?
拼写纠错是如何实现的?