Java后端常见面试题GitHub一夜爆火(建义收藏)

前言:

在这金三银四的跳槽季,这么多的面试面经你都是需要到的,对这些越详细,对你以后的工资问题越高,整理出了这一些,还有很多,到时候末端会有介绍。“不积跬步,无以至千里”,希望未来的你能成为:有梦为马 随处可栖!加油

(一)Java基础

1. wait和sleep的区别

这两个方法来自不同的类分别是Thread和Object

最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用(使用范围)

sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

sleep是Thread类的静态方法。sleep的作用是让线程休眠制定的时间,在时间到达时恢复,也就是说sleep将在接到时间到达事件事恢复线程执行。wait是Object的方法,也就是说可以对任意一个对象调用wait方法,调用wait方法将会将调用者的线程挂起,直到其他线程调用同一个对象的notify方法才会重新激活调用者。

2. synchronized底层原理 是可重入锁吗

JVM基于进入和退出Monitor对象来显示方法同步和代码块同步,但两者的实现细节不一样。代码块同步是使用monitorenter和monitorexit指令实现的,而方法同步是使用另外一种方式实现的。monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法的结束处和异常处,JVM保证每个monitorenter必须有对应的monitorexit与之配对。

Synchronize是可重入锁,一个获得锁的线程可以再次进入一个同步块方法

3. CAS原理,CAS会有什么问题,怎么解决ABA问题(可以谈Java内存模型)

CAS并发原语提现在Java语言中就是sun.miscUnSafe类中的各个方法。调用UnSafe类中的CAS方法,JVM会帮我实现CAS汇编指令.这是一种完全依赖于硬件 功能,通过它实现了原子操作。再次强调,由于CAS是一种系统原语,原语属于操作系统用于范畴,是由若干条指令组成,用于完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许中断,也即是说CAS是一条原子指令,不会造成所谓的数据不一致的问题。

CAS问题:

ABA

循环时间长,开销大

只能保证一个变量的原子操作

解决ABA:版本号,JDK的Atomic包里提供了一个类Atomic包里提供了一个AtomicStampedReference来解决ABA问题

4. HashMap数据结构线程安全吗,举个例子HashMap怎么线程不安全

不安全,在resize的时候,两个线程同时操作会出现链表成环问题,导致查找一个不存在的key的时候,CPU利用率达到100%,解决方:使用ConcurrentHashMap

5. java的基本数据类型和字节数

整型:byte(1字节)、short(2字节)、int(4字节)、long(8字节)

浮点型:float(4字节)、double(8字节)

字符:char(2字节)

布尔:boolean(1位)

6. Java,volatile关键字

volatile 是 java 提供的最轻量级的同步机制,当变量定义为 volatile 后,可以保证此变量对多线程的可见性。多个线程可以读到内存中最新的值。volatile可以保证可见性和有序性,不能保证原子性。根据总线上的嗅探机制修改共享变量会使其他线程中的缓存变量失效,但不是立即从主内存中更新值,而是等到下一次use的时候,发现值是无效的,才会从主内存中读取新的值。

7. String,StringBuffer,StringBuilder区别

StringBuilder不是线程安全的,StringBuffer是线程安全的。

Java 中字符串属于对象,String的值是不可变的,这就导致每次对String的操作都会生成新的String对象。

当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

8. Concurrent下面的包的原理

Java的CAS会使用现代处理器上提供的高效机器级别原子指令,这些原子指令以原子方式对内存执行读-改-写操作,这是在多处理器中实现同步的关键。同时,volatile变量的读/写和CAS可以实现线程之间的通信。把这些特性整合在一起,就形成了整个concurrent包得以实现的基石。如果我们仔细分析concurrent包的源代码实现,会发现一个通用化的实现模式:

首先,声明共享变量为volatile;

然后,使用CAS的原子条件更新来实现线程之间的同步;

同时,配合以volatile的读/写和CAS所具有的volatile读和写的内存语义来实现线程之间的通信。

AQS,非阻塞数据结构和原子变量类(
java.util.concurrent.atomic包中的类),这些concurrent包中的基础类都是使用这种模式来实现

的,而concurrent包中的高层类又是依赖于这些基础类来实现的。从整体来看,concurrent包的实现示意图如下:

9. Java集合框架、map

10. Java 异常

所有异常都是由trowable类继承而来,但在下一层立即分解为两个分支:Error和Exception

Error类层次结构描述了java运行时系统的内部错误和资源耗尽错误。应用程序不应该抛出这种类型的对象。如果出现类这样的内部错误,除了报告给用户,并尽力使程序安全的终止外,再也无能无力类,这种情况很少遇见。

在设计Java程序时,需要关注Exception层次结构,这个层次结构又分解为两个分支:一个分支派生于RuntimeException;另一个包含其他异常。划分两个分支的规则是:由程序错误导致的异常属于RuntionException;而程序本身没有问题,但像I/O错误这类问题导致的异常属于其他异常

11. Object有哪些方法

9个

clone、getClass、toString、finalize、equals、hashCode、wait、notify、notifyAll

12. 深拷贝、浅拷贝

clone方法执行的是浅拷贝

对于对象中的引用类型,浅拷贝复制引用,深拷贝复制值

数组中的clone():

一维数组:深克隆;(重新分配空间,并将元素复制过去)

二维数组:浅克隆。(只传递引用)

如何实现二维数组的深克隆呢?对每一维数组调用clone方法。

(二)数据结构

1. B树、B+树、红黑树,数据结构是什么,查询复杂度是多少

B、B+树:

动态查找树主要包括:二叉查找树,平衡二叉树,红黑树,B树,B-树,查找的时间复杂度就为O(log2N),通过对数就可以发现降低树的深度就会提高查找效率。在大数据存储过程,大量的数据会存储到外存磁盘,外存磁盘中读取与写入某数据的时候,首先定位到磁盘中的某一块,这就有个问题:如何才能有效的查找磁盘中的数据呢,这就需要一种高效的外存数据结构,也就引出了下面的课题。

辅助索引把一个复杂度大概为log2(N)的二次搜索问题变成了logb(N)磁盘读,b是数据块的因素(树的分叉数)(也就是一个数据块容纳的条目数量)

红黑树的复杂度:包含n个内部节点的红黑树的高度是 O(log(n))。

1. B树

B树也称B-树,它是一颗多路平衡查找树。二叉树我想大家都不陌生,其实,B树和后面讲到的B+树也是从最简单的二叉树变换而来的,并没有什么神秘的地方,下面我们来看看B树的定义。

每个节点最多有m-1个关键字(可以存有的键值对)。

根节点最少可以只有1个关键字。

非根节点至少有m/2个关键字。

每个节点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。

所有叶子节点都位于同一层,或者说根节点到每个叶子节点的长度都相同。

每个节点都存有索引和数据,也就是对应的key和value。

总结:5阶B树,一个节点最多4个关键字,最少2个关键字,关键字顺序排列,每个节点既包含索引也有数据,叶子结点都在同一层,典型的B树:

2. B+树

B+树其实和B树是非常相似的,我们首先看看相同点。

根节点至少一个元素

非根节点元素范围:m/2 <

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值