找不到工作的面试者总结
提示:写文章的时候,我还在找工作!!!
文章目录
- 找不到工作的面试者总结
- 前言
- 一、JAVA面死题
-
- 1. OOP是什么
- 2. 重载与重写的区别
- 3. java基本类型
- 4. String、StringBuffer、StringBuilder的区别
- 5. 接口和抽象类区别
- 6. 什么是自动拆装箱 int 和 Integer 有什么区别
- 7. ==和 equals 区别
- 8. final 、 finally 、 finalize
- 9.object有哪些方法?
- 10. 集合有哪些?
- 11. ArrarList 和 LinkedList 区别
- 12. HashMap底层,为什么要这样用?
- 13. HashMap 和 HashTable 区别
- 14. 线程的创建方式
- 15. 请写出你最常见的 5 个 RuntimeException
- 16. java的反射你是如果理解的
- 17. 什么是 java 序列化, 如何实现 java 序列化
- 18. java中锁
- 19. sleep 和 wait 区别
- 20. jvm分哪几个区?
- 21. java垃圾回收机制有哪些?
- 22. 如何判断一个对象是否存活?
- 23. 什么是线程池,线程池有哪些?
- 24. java单列模式懒汉式和饿汉式了解吗?
- 24.线程池的底层原理了解吗?
- 25.常见线程安全的并发容器有哪些
- 26.cas机制你了解吗?
- 27.Atomic 原子类了解多少 原理是什么?
- 28.synchronized 和 lock 区别?
- 29. 了解 ConcurrentHashMap 吗 为什么性能比HashTable 高, 说下原理
- 30.是否了解 volatile 关键字?
- 31.类加载过程?
- 32.类加载器有哪些?
- 33.Java中&&和&,||和|的区别?
- 34.jvm虚拟机常用命令
- 35.java中左右移位运算
- 36、NIO、AIO、BIO了解吗?
- 37、多线程场景题:
- 二、Mysql面死题
- 三. spring面死题
- 四、redis面死题
-
- 1、介绍下 Redis Redis 有哪些数据类型 ?
- 2、Redis 提供了哪几种持久化方式
- 3、Redis 为什么是单线程的
- 4、为什么 Redis 的操作是原子性的, 怎么保证原子性的
- 5、Redis 有事务吗
- 6.Redis 数据和 MySQL 数据库的一致性如何实现
- 7、 缓存击穿, 缓存穿透, 缓存雪崩的原因和解决方案(或者说使用缓存的过程中有没有遇到什么问题, 怎么解决的)
- 8、哨兵模式是什么样得?
- 9、Redis 为什么快?
- 10、Redis 常见性能问题和解决方案
- 11、MySQL 里有大量数据, 如何保证 Redis 中的数据都是热点数据
- 12、说说 Redis 哈希槽的概念
- 五、Mybatis面死题
- 六、Spring Boot面死题
- 七、 SpringCloud面试题
- 八、Hadoop面死题
- 九、Zookeeper 面死题
- 十、Flume面死题
- 十一、Datax面死题
- 1、DataX 和 Sqoop 区别如下:
- 2、速度控制
- 3、内存调整
- 4、空值处理
前言
提示:学了这些也找不到工作,计算机真的崩了,如果看到这篇文章,别干java,别干大数据,肺腑之言。
一、JAVA面死题
1. OOP是什么
OOP(Object Oriented Programming)即面向对象编程,面向对象的三大特征:封装、继承、多态
2. 重载与重写的区别
方法的重载是编译时多态,方法的重写是运行时多态
重载:重载发生在一个类中,同名的方法,不同的参数类型或者不同的参数个数
重写:重写发送在子类和父类之间,要求子类的重写方法和父类的被重写方法的方法名字、方法参数个数、方法类型、返回类型相同,访问权限不能比父类的低。
3. java基本类型
java基本类型八个,六种数字类型(四个整数型,两个浮点型),一种字符串型,还有一种布尔型。
byte、short、int、long、float、double、boolean、char
注意:string是引用类型
4. String、StringBuffer、StringBuilder的区别
String:字符串由final修饰的常量,存在常量池中,所以他是线程安全的。
StringBuffer:它使用了synchronize关键字,对方法进行了同步处理,所以线程是安全的。
StringBuilder:执行效率虽然高,但是因为线程不安全,所以不建议在多线程的环境下对同一个StringBuilder对象进行操作
5. 接口和抽象类区别
抽象类(abstract):需要子类继承、单继承、可以有构造方法,访问修饰符可以有public,protected和default、可以有成员变量,可以有main方法。
接口(interface):需要子类实现接口、多实现、不能有构造方法,访问修饰符只能是public、只能有常量,不能有main方法
6. 什么是自动拆装箱 int 和 Integer 有什么区别
底层是通过 Integer.valueOf()和 Integer.intValue() 方法实现 。 Integer 的默认值是
null, int 的默认值是 0
所以在[-128,127]区间内,==比较的时候,值总是相等的(指向的是同一对象),在这个区间外是不等的,
//① 在-128~127之外的数 false
Integer i1 =200;
Integer i2 =200;
System.out.println("i1==i2:"+(i1==i2));
//② 在-128~127之内的数 true
Integer i3 =100;
Integer i4 =100;
System.out.println("i3==i4:"+(i3==i4));
//③ 不使用自动装箱功能时 false
Integer i5 = new Integer(100);
Integer i6 = new Integer(100);
System.out.println("i5==i6:"+(i5==i6));
//与int比较的时候数值相同则始终是true 因为java自动拆箱功能
7. ==和 equals 区别
==:如果比较的是基本数据类型, 那么比较的是变量的值 如果比较的是引用数据类型, 那么比较的是地址值 (两个对象是否指向同一块内 存)
equals:如果没重写equals方法比较的是两个对象的地址值
如果重写了比较的是内容,equals是从object类中继承的,默认实现方法是双等
8. final 、 finally 、 finalize
final修饰符(关键字):被final修饰的类,就意味着不能再派生出新的子类,不能作为父类而被子类继承。因此一个类不能既被abstract声明,又被final声明。将变量或方法声明为final,可以保证他们在使用的过程中不被修改。被声明为final的变量必须在声明时给出变量的初始值,而在以后的引用中只能读取。被final声明的方法也同样只能使用,即不能方法重写。
finally是在异常处理时提供finally块来执行任何清除操作。不管有没有异常被抛出、捕获,finally块都会被执行。try块中的内容是在无异常时执行到结束。catch块中的内容,是在try块内容发生catch所声明的异常时,跳转到catch块中执行。finally块则是无论异常是否发生,都会执行finally块的内容,所以在代码逻辑中有需要无论发生什么都必须执行的代码,就可以放在finally块中。
finalize是方法名。java技术允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在object类中定义的,因此所有的类都继承了它。子类覆盖finalize()方法以整理系统资源或者被执行其他清理工作。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的
9.object有哪些方法?
protected Object clone()—>创建并返回此对象的一个副本 。
boolean equals(Object obj)—>指示某个其他对象是否与此对象“相等
protected void finalize()—>当垃圾回收器确定不存在对该对象的更多引用时, 由 对象的垃圾回收器调用此方法 。
Class<?extendsObject> getClass()—>返回一个对象的运行时类。
int hashCode()—>返回该对象的哈希码值 。 void notify()—>唤醒在此对象监视器上等待的单个线程。
void notifyAll()—>唤醒在此对象监视器上等待的所有线程。 String toString()—>返回该对象的字符串表示
10. 集合有哪些?
11. ArrarList 和 LinkedList 区别
ArrayList 是实现了基于动态数组的数据结构, LinkedList 基于链表的数据结构
对于随机访问 get 和 set, ArrayList 效率优于 LinkedList, 因为 LinkedList 要移 动指针 。
对于新增和删除操作 add 和 remove, LinkedList 比较占优势, 因为 ArrayList 要 移动数据 。 这一点要看实际情况的。若只对单条数据插入或删除, ArrayList 的速 度反而优于 LinkedList 。但若是批量随机的插入删除数据, LinkedList 的速度大大 优于 ArrayList. 因为 ArrayList 每插入一条数据, 要移动插入点及之后的所有数 据 。
12. HashMap底层,为什么要这样用?
HashMap 底层是 数组+链表+红黑树 数组 Node<K,V>[] table ,哈希表, 根据对象的 key 的hash 值判断在数组里面是哪个节点
链表的作用是解决 hash 冲突, 将 hash 值取模之后的对象存在一个链表放在 hash值对应的槽位
红黑树 JDK8 使用红黑树来替代超过 8 个节点的链表,发送哈希碰撞,会带来链化,效率会变低,引入红黑树会提高查找效率从原来的 O(n)到 O(logn)
当链表长度大于8,且总数据量大于64的时候,链表就会转化成红黑树,
当前存入数据大于阈值即发生扩容或者存入数据到某一条链表时,此时该链表数据个数大于8,且数组总数量小于64即发生扩容每次扩容为初始容量的2倍
13. HashMap 和 HashTable 区别
HashTable 是线程安全的,而 HashMap 不是。
HashMap 的性能要比 HashTable 更好,因为HashTable 采用了全局同步Synchronized来保证安全性,对性能影响较大
HashMap 只有 containsValue 和 containsKey 方法; HashTable 有 contains 、 containsKey 和 containsValue 三个方法, 其中 contains 和 containsValue 方法功 能相同 。
Hashtable 中, key 和 value 都不允许出现 null 值 。HashMap 中, null 可以作为 键, 这样的键只有一个; 可以有一个或多个键所对应的值为 null。
HashTable 在不指定容量的情况下的默认容量为 11, 而 HashMap 为 16 , Hashtable 不要求底层数组的容量一定要为 2 的整数次幂, 而 HashMap 则要求一 定为 2 的整数次幂。
Hashtable 扩容时, 将容量变为原来的 2 倍加 1, 而 HashMap 扩容时, 将容量变 为原来的 2 倍 。
14. 线程的创建方式
线程的5种状态: 新建状态、就绪状态、运行状态、阻塞状态、死亡状态
1、继承 Thread 类创建线程
2、实现 Runnable 接口创建线程
3、实现callable接口和创建Future类创建线程,有返回值
4、使用线程池创建线程
5、使用匿名线程创建
15. 请写出你最常见的 5 个 RuntimeException
java.lang.NullPointerException 空指针异常; 出现原因: 调用了未经初始化的对象或者是不存在的对象 。
java.lang.ClassNotFoundException 指定的类找不到; 出现原因: 类的名称和路径加载错误; 通常都是程序试图通过 字符串来加载某个类时可能引发异常 。
java.lang.NumberFormatException字符串转换为数字异常; 出现原因: 字符型数据中包含非数字型字符 。
java.lang.IndexOutOfBoundsException 数组角标越界异常, 常见于操作数组对象时发生 。
java.lang.IllegalArgumentException 方法传递参数错误
java.lang.ClassCastException 数据类型转换异常。
16. java的反射你是如果理解的
在运行状态下,任何一个类,你都能知道它的所有方法和属性,对任何一个对象,你都能调用它的方法和属性,这种动态调用和获取的方法叫做反射机制
获取Class对象的三种方式
1 Object ——> getClass();
2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
3 通过Class类的静态方法:forName(String className)(常用)
17. 什么是 java 序列化, 如何实现 java 序列化
序列化是一种用来处理对象流的机制, 所谓对象流也就是将对象的内容进行流 化 。可以对流化后的对象进行读写操作, 也可将流化后的对象传输于网络之间
序列化的实现: 将需要被序列化的类实现 Serializable 接 口, 该接口没有 需 要 实 现 的 方 法, implements Serializable 只是为了标注该对象是可被序列化的,然后使用一个输出流(如: FileOutputStream)来构造一个 ObjectOutputStream(对象流) 对象, 接着, 使用 ObjectOutputStream 对象的 writeObject(Object obj)方法就可以将 参数为 obj 的对象写出(即保存其状态), 要恢复的话则用输入流。
18. java中锁
乐观锁:采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作
悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在读写数据的时候都会上锁,这样别人想读写这个数据就会 block 直到拿到锁
自旋锁:线程不需要进入阻塞状态,直接在自旋,等待锁释放直接获取,减少线程切换的消耗,但自旋消耗cpu。
非公平锁:JVM 随机就近原则分配锁的机制则称为不公平锁,非公平锁实际执行的效率要远超公平锁,除非程序有特殊需要,否则最常用非公平锁的分配机制。
公平锁:公平锁指的是锁的分配机制是公平的,通常先对锁提出获取请求的线程会先被分配到锁加锁前检查是否有排队等待的线程,优先排队等待的线程,先来先得
同步锁: 当多个线程同时访问同一个数据时,很容易出现问题。为了避免这种情况出现,我们要保证线程同步互斥,就是指并发执行的多个线程。在同一时间内只允许一个线程访问共享数据
死锁:就是多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。以下是死锁的4个必要条件,防止死锁只要破坏其中一条
1、互斥条件:一个资源每次只能被一个线程使用
2、不可剥夺条件:一个线程已经获得的资源, 在未使用完之前, 不能被强行剥夺
3、请求和保持条件:一个线程在阻塞等待某个资源时, 不释放已占有资源
4、循环等待条件:若干线程形成头尾相接的循环等待资源关系
锁优化通常可以:减小锁粒度比如分段锁,实现锁分离,让读写分离,实现锁粗化让锁的时间尽量短
Synchronized,它就是一个:非公平,悲观,独享,互斥,可重入的重量级锁
ReentrantLock,它是一个:默认非公平但可实现公平的,悲观,独享,互斥,可重入,重量级锁。
ReentrantReadWriteLocK,它是一个,默认非公平但可实现公平的,悲观,写独享,读共享,读写,可重入,重量级锁。
19. sleep 和 wait 区别
sleep:不释放锁资源
wait:释放锁资源,一值等待需要notify唤醒,必须配合 synchronized 一起使用, 不然在运行时就会抛出 IllegalMonitorStateException 异常
20. jvm分哪几个区?
1、方法区(永久代):存储类的信息、常量、静态变量等,被线程共享
2、虚拟机栈(java栈):存储局部变量和引用、运算结果和运算操作数、动态链接(将常量池中的符号引用在运行期转化为直接引用)、方法出口等信息,不被线程共享
3、本地方法栈:本地方法栈和虚拟机栈类似, 只不过本地方法栈为 Native 方法服务
4、堆:java 堆是所有线程所共享的一块内存, 在虚拟机启动时创建, 几乎所有的对象实例 都在这里创建, 因此该区域经常发生垃圾回收操作 。
5、程序计数器:内存空间小, 字节码解释器工作时通过改变这个计数值可以选取下一条需要执行的字节码指令, 分支 、循环 、跳转 、异常处理和线程恢复等功能都需要依赖这个计数 器完成 。该内存区域是唯一一个 java虚拟机规范没有规定任何 OOM 情况的区域 。
21. java垃圾回收机制有哪些?
采用分区分代回收思想:
1、复制算法:年轻代中使用的是 Minor GC, 这种 GC 算法采用的是复制算法 (Copying),效率高,内存占用大,使用在占空间比较小 、刷新次数多的新生区
2、标记清除法:老年代一般是由标记清除或者是标记清除与标记整理的混合实现,效率比较低, 会差生碎片。
3、标记整理法:效率低速度慢,需要移动对象,但不会产生碎片 。
cms:
CMS采用 标记-清理 的算法,标记出垃圾对象,清除垃圾对象。算法是基于老年代执行的,因为新生代产生无法接受该算法产生的碎片垃圾。优点:并发收集,低停顿不足:无法处理浮动垃圾,并发收集会造成内存碎片过多由于并发标记和并发清理阶段都是并发执行,所以会额外消耗CPU资源
g1:
G1的出现就是为了替换jdk1.5种出现的CMS,这一点已经在jdk9的时候实现了,jdk9默认使用了G1回收器,移除了所有CMS相关的内容。G1和CMS相比,有几个特点:控制回收垃圾的时间:这个是G1的优势,可以控制回收垃圾的时间,还可以建立停顿的时间模型,选择一组合适的Regions作为回收目标,达到实时收集的目的空间整理:和CMS一样采用标记-清理的算法,但是G1不会产生空间碎片,这样就有效的使用了连续空间,不会导致连续空间不足提前造成GC的触发G1把Java内存拆分成多等份,多个域(Region),逻辑上存在新生代和老年代的概念,但是没有严格区分
22. 如何判断一个对象是否存活?
1、引用计数法:每个对象设置一个计数器,每当有一个对象引用+1,失效后-1,为0时没有引用被回收,无法解决循环依赖问题。
2、可达性算法(引用链法):提供gcroots的对象作为起点,向下搜索,当一个对象到gcroots没有任何引用时,证明不可达,回收掉
23. 什么是线程池,线程池有哪些?
线程池是事先将线程放在同一个容器中,当使用的时候不用new线程,而是去线程池中拿线程,节省了线程开销,提供了代码效率。
1、newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要, 可灵活回收空闲线程, 若无可回收, 则新建线程。
ExecutorServicenewCachedThreadPool=Executors.newCachedThreadPool();
2、newFixedThreadPool 创建一个指定工作线程数量的线程池 。每当提交一个任务就创建一个工作线程, 如果工作线程数量达到线程池初始的最大数, 则将提交的任务存入到池队列中 。
ExecutorServicenewFixedThreadPool=Executors.newFixedThreadPool(4);
3、newSingleThreadExecutor 创建一个单线程化的 Executor, 即只创建唯一的工作者线程来执行任务, 它只会用唯一的工作线程来执行任务, 保证所有任务按照指定顺序。
ExecutorServicenewSingleThreadExecutor=Executors.newSingleThreadExecutor();
4、newScheduleThreadPool 创建一个定长的线程池, 而且支持定时的以及周期性的任务执行 。例如延迟 3 秒 执行。
ScheduledExecutorService newScheduledThreadPool =Executors.newScheduledThreadPool(4);
24. java单列模式懒汉式和饿汉式了解吗?
饿汉式:是立即加载的方式,无论是否会用到这个对象,都会加载。
public class GiantDragon {
//私有化构造方法使得该类无法在外部通过new 进行实例化
private GiantDragon(){
System.out.println("私有化构造方法");
}
//准备一个类属性,指向一个实例化对象。 因为是类属性,所以只有一个
private static GiantDragon instance = new GiantDragon();
//public static 方法,提供给调用者获取12行定义的对象
public static GiantDragon getInstance(){
return instance;
}
}
懒汉式:是延迟加载的方式,只有使用的时候才会加载。并且有线程安全的考量。用双端检测其实是因为每次访问只有在第一次访问的时候才要加锁,其他时间直接判断是不是null就返回。
public class GiantDragon2 {
//GiantDragon2 进行实例化
private GiantDragon2(){
System.out.println("私有化构造方法");
}
//准备一个类属性,用于指向一个实例化对象,但是暂时指向null
private static GiantDragon2 instance;
//public static 方法,返回实例对象 (非线程安全的,不推荐使用该写法)
public static GiantDragon2 getInstance(){
//第一次访问的时候,发现instance没有指向任何对象,这时实例化一个对象
if(null==instance){
instance = new GiantDragon2();
}
//返回 instance指向的对象
return instance;
}
// 线程安全的,并且通过非空判断提升性能(因为如果只上锁,那么每次调用的时候都会上锁,事实上只有第一次创建对象的时候才需要加锁)
public static GiantDragon2 getInstance(){
if(instance == null