2023年Java面经(大厂面试必备)100题_第1页
2023年Java面经(大厂面试必备)100题_第2页
2023年Java面经(大厂面试必备)100题_第3页
2023年Java面经(大厂面试必备)100题_第4页
2023年Java面经(大厂面试必备)100题_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

2023年Java面经(大厂面试必备)100题(一)

一、基础篇

1、面向对象和面向过程的区别?

【仅供参考】

面向对象和面向过程是一种软件开发思想。

面向过程就是分析出解决问题所需要的步骤,然后用函数按这些步骤实现,使用的时候依次调

用就可以了。

面向对象是把构成问题事务分解成各个对象,分别设计这些对象,然后将他们组装成有完整功

能的系统。面向过程只用函数实现,面向对象是用类实现各个功能模块。

以五子棋为例,面向过程的设计思路就是首先分析问题的步骤:

1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、

判断输赢,8、返回步骤2,9、输出最后结果。把上面每个步骤用分别的函数来实现,问题就

解决了。

而面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为:

黑白双方

棋盘系统,负责绘制画面

规则系统,负责判定诸如犯规、输赢等。

黑白双方负责接受用户的输入,并告知棋盘系统棋子布局发生变化,棋盘系统接收到了棋子的

变化的信息就负责在屏幕上面显示出这种变化,同时利用规则系统来对棋局进行判定。

2、Files的常用方法都有哪些?

【仅供参考】

Files.existsO:检测文件路径是否存在。

Files.createFileO:创建文件。

Files.createDirectory():创建文件夹。

Files,delete():删除一个文件或目录。

Files.copy():复制文件。

Files,move():移动文件。

Files.size():查看文件个数。

Files.read():读取文件。

Files,write():写入文件。

3、用最有效率的方法计算2乘以8?

【仅供参考】

2«3。进阶:通常情况下,可以认为位运算是性能最高的。但是,其实编译器现在已经“非

常聪明了”,很多指令编译器都能自己做优化。所以在实际实用中,我们无需特意去追求实用

位运算,这样不仅会导致代码可读性很差,而且某些自作聪明的优化反而会误导编译器,使得

第1/24页

编译器无法进行更好的优化。

4、JDK和JRE有什么区别?

【仅供参考】

JDK:JavaDevelopmentKit的简称,Java开发工具包,提供了Java的开发环境和运行环

境。

JRE:JavaRuntimeEnvironment的简称,Java运行环境,为Java的运行提供了所需环境。

具体来说JDK其实包含了JRE,同时还包含了编译Java源码的编译器Javac,还包含了很多

Java程序调试和分析的工具。简单来说:如果你需要运行Java程序,只需安装JRE就可以

了,如果你需要编写Java程序,需要安装JDKO

5、构造器是否可被重写?

【仅供参考】

Constructor不能被override(重写),但是可以overload(重载),所以你可以看到个

类中有多个构造函数的情况。

6、Java支持多继承吗?

【仅供参考】

java中,类不支持多继承。接口才支持多继承。接口的作用是拓展对象功能。当一个子接口继

承了多个父接口时,说明子接口拓展了多个功能。当一个类实现该接口时,就拓展了多个的功

能。

Java不支持多继承的原因:

出于安全性的考虑,如果子类继承的多个父类里面有相同的方法或者属性,子类将不知道具体

要继承哪个。

Java提供了接口和内部类以达到实现多继承功能,弥补单继承的缺陷。

7、抽象类能使用final修饰吗?

【仅供参考】

不能,定义抽象类就是让其他类继承的,如果定义为final该类就不能被继承,这样彼此就会

产生矛盾,所以final不能修饰抽象类,编辑器也会提示错误信息:

8^两个对象的hashCode()相同,则equals()也一定为true,对吗?

【仅供参考】

不对,两个对象的hashCode()相同,equals()不一定true。

代码示例:

Stringstrl="通话”;

Stringstr2="重地";

System,out.println(String.format(/?strl:%d|str2:%d”,strl.hashCode(),str2.

hashCode()));

System,out.println(strl.equals(str2));

执行的结果:

第2/24页

strl:1179395.str2:1179395

false

代码解读:很显然“通话”和“重地”的hashCode()相同,然而equals()则为false,因

为在散列表中,hashCode()相等即两个键值对的哈希值相等,然而哈希值相等,并不一定能得

出键值对相等。

9^抽象类(abstractclass)和接口(interface)有什么区别?

【仅供参考】

抽象类只能单继承,接口可以多实现。

抽象类可以有构造方法,接口中不能有构造方法。

抽象类中可以有成员变量,接口中没有成员变量,只能有常量(默认就是publicstatic

final)

抽象类中可以包含非抽象的方法,在Java7之前接口中的所有方法都是抽象的,在Java8

之后,接口支持非抽象方法:default方法、静态方法等。Java9支持私有方法、私有静态方

法。

抽象类中的方法类型可以是任意修饰符,Java8之前接口中的方法只能是public类型,Java

9支持private类型。

设计思想的区别:

接口是自上而下的抽象过程,接口规范了某些行为,是对某一行为的抽象。我需要这个行为,

我就去实现某个接口,但是具体这个行为怎么实现,完全由自己决定。

抽象类是自下而上的抽象过程,抽象类提供了通用实现,是对某一类事物的抽象。我们在写实

现类的时候,发现某些实现类具有几乎相同的实现,因此我们将这些相同的实现抽取出来成为

抽象类,然后如果有一些差异点,则可以提供抽象方法来支持自定义实现。

我在网上看到有个说法,挺形象的:

普通类像亲爹,他有啥都是你的。

抽象类像叔伯,有一部分会给你,还能指导你做事的方法。

接口像干爹,可以给你指引方法,但是做成啥样得你自己努力实现。

10、Object常用方法有哪些?

【仅供参考】

Java面试经常会出现的一道题目,Object的常用方法。下面给大家整理一下。

Object常用方法有:toStringO、equals。、hashCode。、clone。等。

11、普通类和抽象类有哪些区别?

【仅供参考】

普通类不能包含抽象方法,抽象类可以包含抽象方法。

抽象类不能直接实例化,普通类可以直接实例化。

12、Java中10流分为几种?

【仅供参考】

按功能来分:输入流(input)、输出流(output)o

第3/24页

按类型来分:字节流和字符流。

字节流和字符流的区别是:字节流按8位传输以字节为单位输入输出数据,字符流按16位传

输以字符为单位输入输出数据。

13、接口和抽象类有什么区别?

【仅供参考】

实现:抽象类的子类使用extends来继承;接口必须使用implements来实现接口。

构造函数:抽象类可以有构造函数;接口不能有。

实现数量:类可以实现很多个接口;但是只能继承一个抽象类。

访问修饰符:接口中的方法默认使用public修饰;抽象类中的方法可以是任意访问修饰符。

14、如何实现对象克隆?

【仅供参考】

实现Cloneable接口,重写clone0方法。这种方式是浅拷贝,即如果类中属性有自定义引用

类型,只拷贝引用,不拷贝引用指向的对象。如果对象的属性的Class也实现Cloneable接

口,那么在克隆对象时也会克隆属性,即深拷贝。

结合序列化,深拷贝。

通过org.apache,commons中的工具类BeanUtils和PropertyUtils进行对象复制。

15、throw和throws的区别是什么?

【仅供参考】

Java中的异常处理除了包括捕获异常和处理异常之外,还包括声明异常和抛出异常,可以通过

throws关键字在方法上声明该方法要抛出的异常,或者在方法内部通过throw抛出异常对

象。

throws关键字和throw关键字在使用上的几点区别如下:

throw关键字用在方法内部,只能用于抛出一种异常,用来抛出方法或代码块中的异常,受查

异常

和非受查异常都可以被抛出。

throws关键字用在方法声明上,可以抛出多个异常,用来标识该方法可能抛出的异常列表。一

方法用throws标识了可能抛出的异常列表,调用该方法的方法中必须包含可处理异常的代

码,否

则也要在方法签名中用throws关键字声明相应的异常。

16、常见的RuntimeException有哪些?

【仅供参考】

ClassCastException(类转换异常)

IndexOutOfBoundsException(数组越界)

NullPointerException(空指针)

ArrayStoreException(数据存储异常,操作数组时类型不一致)

还有10操作的BufferOverflowException异常

第4/24页

17、final,finally、finalize有什么区别?

【仅供参考】

final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重

写、

修饰变量表示该变量是一个常量不能被重新赋值。

finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方

finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的

代码。

finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,Java中允许使

finalize。方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。

18、Error和Exception区别是什么?

【仅供参考】

Error类型的错误通常为虚拟机相关错误,如系统崩溃,内存不足,堆栈溢出等,编译器不会

对这

类错误进行检测,JAVA应用程序也不应对这类错误进行捕获,一旦这类错误发生,通常应用程

会被终止,仅靠应用程序本身无法恢复;

Exception类的错误是可以在应用程序中进行捕获并处理的,通常遇到这种错误,应对其进行

理,使应用程序可以继续正常运行。

19、try-catch-finally中哪个部分可以省略?

【仅供参考】

catch可以省略

更为严格的说法其实是:try只适合处理运行时异常,try+catch适合处理运行时异常+普通异

常。

也就是说,如果你只用try去处理普通异常却不加以catch处理,编译是通不过的,因为编译器

硬性

规定,普通异常如果选择捕获,则必须用catch显示声明以便进一步处理。而运行时异常在编译

没有如此规定,所以catch可以省略,你加上catch编译器也觉得无可厚非。

理论上,编译器看任何代码都不顺眼,都觉得可能有潜在的问题,所以你即使对所有代码加上

try,代码在运行期时也只不过是在正常运行的基础上加一层皮。但是你一旦对一段代码加上

try,

就等于显示地承诺编译器,对这段代码可能抛出的异常进行捕获而非向上抛出处理。如果是普

通异

常,编译器要求必须用catch捕获以便进一步处理;如果运行时异常,捕获然后丢弃并且

第5/24页

+finally扫

尾处理,或者加上catch捕获以便进一步处理。

至于加上finally,则是在不管有没捕获异常,都要进行的“扫尾”处理。

20、try-catch-finally中,如果catch中return了,finally还会执行吗?

【仅供参考】

答:会执行,在return前执行。

注意:在finally中改变返回值的做法是不好的,因为如果存在finally代码块,try中的

return语

句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后再向调用者返回其

值,

然后如果在finally中修改了返回值,就会返回修改后的值。显然,在finally中返回或者

修改返回

值会对程序造成很大的困扰,C#中直接用编译错误的方式来阻止程序员干这种龌龊的事

情,Java

中也可以通过提升编译器的语法检查级别来产生警告或错误。

二、高级篇

KIterator怎么使用?有什么特点?

【仅供参考】

Iterator使用代码如下:

List<String>list=newArrayListO();

Iterator<String>it=list,iterator();

while(it.hasNext()){

Stringobj=it.next();

System,out.printin(obj);

)

Iterator的特点是更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛

出ConcurrentModificationException异常。

2、说一下IlashMap的实现原理?

【仅供参考】

HashMap基于Hash算法实现的,我们通过put(key,value)存储,get(key)来获取。当传入

key时,HashMap会根据key.hashCode()计算出hash值,根据hash值将value保存在

bucket里。当计算出的hash值相同时,我们称之为hash冲突,HashMap的做法是用链表和

红黑树存储相同hash值的value。当hash冲突的个数比较少时,使用链表否则使用红黑

树。

第6/24页

3、在Queue中poll。和remove。有什么区别?

【仅供参考】

相同点:都是返回第一个元素,并在队列中删除返回的对象。

不同点:如果没有元素poll。会返回null,而remove。会直接抛出

NoSuchElementException异常。

代码示例:

Queue<String>queue=newLinkedList<String>();

queue,offer("string");//add

System,out.printin(queue,poll());

System,out.printin(queue,remove());

System,out.printin(queue,size());

4、ArrayList和Vector的区别。

【仅供参考】

Vector和ArrayList几乎■—致,唯一的区别是Vector在方法上使用了synchronized来保

证线程安全,因此在性能上ArrayList具有更好的表现。

有类似关系的还有:StringBuilder和StringBuffer>HashMap和Hashtable。

5、线程B怎么知道线程A修改了变量

【仅供参考】

(1)volatile修饰变量

(2)synchronized修饰修改变量的方法

(3)wait/notify

(4)while轮询

6、四种线程池的创建:

【仅供参考】

(1)newCachedThreadPool创建一个可缓存线程池

(2)newFixedThreadPool创建一个定长线程池,可控制线程最大并发数。

(3)newScheduledThreadPool创建一个定长线程池,支持定时及周期性任务执行。

(4)newSingleThreadExecutor创建一个单线程化的线程池,它只会用唯一的工作线程来执

行任务。

7、Thread调用start()方法和调用run()方法的区别

【仅供参考】

runO:普通的方法调用,在主线程中执行,不会新建一个线程来执行。

start():新启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到CPU

时间片,就开始执行run()方法。

8、sleep方法和wait方法有什么区别?

第7/24页

【仅供参考】

这个问题常问,sleep方法和wait方法都可以用来放弃CPU一定的时间,不同点在于如果线

程持有某个对象的监视器,sleep方法不会放弃这个对象的监视器,wait方法会放弃这个对象

的监视器

9^什么是Future?

【仅供参考】

在并发编程中,我们经常用到非阻塞的模型,在之前的多线程的三种实现中,不管是继承

thread类还是实现runnable接口,都无法保证获取到之前的执行结果。通过实现Callback

接口,并用Future可以来接收多线程的执行结果。

Future表示一个可能还没有完成的异步任务的结果,针对这个结果可以添加Callback以便在

任务执行成功或失败后作出相应的操作。

10、什么是Java序列化?什么情况下需要序列化?

【仅供参考】

Java序列化是为了保存各种对象在内存中的状态,并且可以把保存的对象状态再读出来。

以下情况需要使用Java序列化:

想把的内存中的对象状态保存到一个文件中或者数据库中时候;

想用套接字在网络上传送对象的时候;

想通过RMI(远程方法调用)传输对象的时候。

11、什么是观察者模式?

【仅供参考】

观察者模式是定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关

依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模

式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者

(Dependents)模式。优点:

观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了

更新接口,使得可以有各种各样不同的表示层作为具体观察者角色;

观察者模式在观察目标和观察者之间建立一个抽象的耦合;

观察者模式支持广播通信;

观察者模式符合开闭原则(对拓展开放,对修改关闭)的要求。

缺点:

如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多

时间;

如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能

导致系统崩溃;

观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知

道观察目标发生了变化。

在观察者模式中有如下角色:

Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每

第8/24页

个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象;

ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具

体主题的内部状态发生改变时,给所有注册过的观察者发送通知;

Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改

通知时更新自己;

ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知

时更新自身的状态。

12、什么情况下会违反迪米特法则?为什么会有这个问题?

【仅供参考】

迪米特法则建议“只和朋友说话,不要陌生人说话”,以此来减少类之间的耦合。

13、10使用了什么设计模式?

【仅供参考】

10使用了适配器模式和装饰器模式。

适配器模式:由于Inputstream是字节流不能享受到字符流读取字符那么便捷的功能,借助

InputStreamReader将其转为Reader子类,因而可以拥有便捷操作文本文件方法;

装饰器模式:将Inputstream字节流包装为其他流的过程就是装饰器模式,比如,包装为

FilelnputStream、ByteArraylnputStream、PipedlnputStream等。

14、使用工厂模式最主要的好处是什么?在哪里使用?

【仅供参考】

工厂模式的最大好处是增加了创建对象时的封装层次。如果你使用工厂来创建对象,之后你可

以使用更高级和更高性能的实现来替换原始的产品实现或类,这不需要在调用层做任何修改。

15、请列举出在JDK中几个常用的设计模式?

【仅供参考】

单例模式(Singletonpattern)用于Runtime,Calendar和其他的一些类中。工厂模式

(Factorypattern)被用于各种不可变的类如Boolean,像Boolean.valueOf,观察者模式

(Observerpattern)被用于Swing和很多的事件监听中。装饰器设计模式(Decorator

designpattern)被用于多个Java10类中。

16、Java内存结构(运行时数据区)

【仅供参考】

程序计数器:线程私有。一块较小的内存空间,可以看作当前线程所执行的字节码的行号指示

器。如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令

的地址;如果正在执行的是Native方法,这个计数器值则为空。

Java虚拟机栈:线程私有。它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存

模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、

方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入

第9/24页

栈到出栈的过程。

本地方法栈:线程私有。本地方法栈与虚拟机栈所发挥的作用是非常相似的,它们之间的区别

不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用

到的Native方法服务。

Java堆:线程共享。对大多数应用来说,Java堆是Java虚拟机所管理的内存中最大的一块。

Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是

存放对象实例,几乎所有的对象实例都在这里分配内存。

方法区:与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息

(构造方法、接口定义)、常量、静态变量、即时编译器编译后的代码(字节码)等数据。方

法区是JVM规范中定义的一个概念,具体放在哪里,不同的实现可以放在不同的地方。

运行时常量池:运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、

接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,

这部分内容将在类加载后进入方法区的运行时常量池中存放。

Stringstr=newString("hello");

上面的语句中变量str放在栈上,用new创建出来的字符串对象放在堆上,而"hello”这个字

面量是放在堆中。

17、队列和栈是什么?有什么区别?

【仅供参考】

队列和栈都是被用来预存储数据的。

队列允许先进先出检索元素,但也有例外的情况,Deque接口允许从两端检索元素。

栈和队列很相似,但它运行对元素进行后进先出进行检索。

18、说一下JVM有哪些垃圾回收算法?

【仅供参考】

标记-清除算法:标记无用对象,然后进行清除回收。缺点:效率不高,无法清除垃圾碎片。

标记-整理算法:标记无用对象,让所有存活的对象都向一端移动,然后直接清除掉端边界以外

的内存。

复制算法:按照容量划分二个大小相等的内存区域,当一块用完的时候将活着的对象复制到另

一块上,然后再把已使用的内存空间一次清理掉。缺点:内存使用率不高,只有原来的一半。

分代算法:根据对象存活周期的不同将内存划分为几块,一般是新生代和老年代,新生代基本

采用复制算法,老年代采用标记整理算法。

19、说一下JVM运行时数据区?

【仅供参考】

不同虚拟机的运行时数据区可能略微有所不同,但都会遵从Java虚拟机规范,Java虚拟机

规范规定的区域分为以下5个部分:

程序计数器(ProgramCounterRegister):当前线程所执行的字节码的行号指示器,字节码

解析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支、循

环、跳转、异常处理、线程恢复等基础功能,都需要依赖这个计数器来完成;

Java虚拟机栈(JavaVirtualMachineStacks):用于存储局部变量表、操作数栈、动态链

第10/24页

接、方法出口等信息;

本地方法栈(NativeMethodStack):与虚拟机栈的作用是一样的,只不过虚拟机栈是服务

Java方法的,而本地方法栈是为虚拟机调用Native方法服务的;

Java堆(JavaHeap):Java虚拟机中内存最大的一块,是被所有线程共享的,几乎所有的对

象实例都在这里分配内存;

方法区(MethedArea):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的

代码等数据。

20、说一下JVM调优的工具?

【仅供参考】

JDK自带了很多监控工具,都位于JDK的bin目录下,其中最常用的是jconsole和

jvisualvm这两款视图监控工具。

jconsole:用于对JVM中的内存、线程和类等进行监控;

jvisualvm:JDK自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存

的变化、gc变化等。

三、Web篇

1、Servlet执行流程

【仅供参考】

web客户向Servlet容器发出HTTP请求;

Servlet容器解析web的HTTP请求.

Servlet容器创建一个HttpRequest对象,在这个对象中封装了http请求信息;

Servlet容器创建一个HttpResponse对象;

Servlet容器(如果访问的该servlet不是在服务器启动时创建的,则先创建servlet实例并调用

init()方法初始化对象)调用HltpServlet的service()方法,把HttpRequest和HttpResponse对

象为service方法的参数传给HttpServlet对象;

HttpServlet调用HttpRequest的有关方法,获取HTTP请求信息;

HttpServlet调用HttpResponse的有关方法,生成响应数据;

Servlet容器把HttpServlet的响应结果传给web客户.

2、一次完整的HTTP请求所经历几个步骤?

【仅供参考】

根据域名和DNS解析到服务器的IP地址(DNS+CDN)

通过ARP协议获得IP地址对应的物理机器的MAC地址

浏览器对服务器发起TCP3次握手

建立TCP连接后发起HTTP请求报文

服务器响应HTTP请求,将响应报文返回给浏览器

短连接情况下,请求结束则通过TCP四次挥手关闭连接,长连接在没有访问服务器的若干时间

后,进行连接的关闭

第11/24页

浏览器得到响应信息中的HTML代码,并请求HTML代码中的资源(如js、css、图片等)

浏览器对页面进行渲染并呈现给用户

3、http和https的区别?

【仅供参考】

区别HTTPHTTPS

协议运行在TCP之上,明文传输,客户端与服务器端都无法验证对方的身份身披SSL(

SecureSocketLayer)外壳的HTTP,运行于SSL上,SSL运行于TCP之上,是添加了加密

和认证机制的HTTPo

端口80443

资源消耗较少由于加解密处理,会消耗更多的CPU和内存资源

证书无需证书需要证书,而证书一般需要向认证机构购买

加密机制无共享密钥加密和公开密钥加密并用的混合加密机制安全性弱由于加密机制,安全

性强

安全性弱由于加密机制,安全性强

4、如何实现跨域?

【仅供参考】

实现跨域有以下几种方案:

服务器端运行跨域设置C0RS等于*;

在单个接口使用注解©CrossOrigin运行跨域;

使用jsonp跨域;

5、什么是长连接和短连接

【仅供参考】

在HTTP/1.0中默认使用短连接。也就是说,客户端和服务器每进行一次HTTP操作,就建立一次

接,任务结束就中断连接

而从HTTP/L1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头

入这行代码:Connection:keep-alive

在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP

接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。Keep-Alive

不会

永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。

实现

长连接需要客户端和服务端都支持长连接

6、前端控制器DispatcherServlet作用?

【仅供参考】

第12/24页

接收请求,响应结果,相当于转发器,中央处理器。有了dispatcherServlet减少了其它组件之

间的耦合度。

用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中

心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。

7、说一下spring的事务隔离?

【仅供参考】

spring有五大隔离级别,默认值为1SOLATION_DEFAULT(使用数据库的设置),其他四个隔离

级别和数据库的隔离级别一致:

ISOLATION_DEFAULT:用底层数据库的设置隔离级别,数据库设置的是什么我就用什么;

ISOLATIONREADUNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就可被其他事务读取

(会出现幻读、脏读、不可重复读);

ISOLATIONREADCOMMITTED:提交读,一个事务提交后才能被其他事务读取到(会造成幻读、不

可重复读),SQLserver的默认级别;

ISOLATIONREPEATABLEREAD:可重复读,保证多次读取同一个数据时,其值都和事务开始时候的

内容是一致,禁止读取到别的事务未提交的数据(会造成幻读),MySQL的默认级别;

ISOLAT1ON_SER1AL1ZABLE:序列化,代价最高最可靠的隔离级别,该隔离级别能防止脏读、不

可重复读、幻读。

「脏读」:表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插入记

录A,此时该事务还未提交,然后另一个事务尝试读取到了记录Ao

「不可重复读」:是指在一个事务内,多次读同一数据。

「幻读」:指同一个事务内多次查询返回的结果集不一样。比如同一个事务A第一次查询时

候有n条记录,但是第二次同等条件下查询却有n+1条记录,这就好像产生了幻觉。发生幻

读的原因也是另外一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记

录的数据内容被修改了,所有数据行的记录就变多或者变少了。

8、spring事务实现方式有哪些?

【仅供参考】

声明式事务:声明式事务也有两种实现方式,基于xml配置文件的方式和注解方式(在类上添

加©Transaction注解)。

编码方式:提供编码的形式管理和维护事务。

9、解释一下什么是aop?

【仅供参考】

aop是面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技

术。

简单来说就是统一处理某一“切面”(类)的问题的编程思想,比如统一处理日志、异常等。

10、常用注解@86211?

【仅供参考】

这个注解是方法级别上的注解,主要添加在©Configuration或@SpringBootConfiguration

第13/24页

注解的类,有时也可以添加在©Component注解的类。它的作用是定义一个Bean。

11、常用注解削。11£iguration?

【仅供参考】

加入了这个注解的类被认为是SpringBoot的配置类,我们知道可以在application,yml设

置一些配置,也可以通过代码设置配置。

如果我们要通过代码设置配置,就必须在这个类上标注Configuration注解。不过Spring

Boot官方推荐SpringBoot项目用SpringBootConfiguration来代替Configuration。

12、运行SpringBoot有哪几种方式?

【仅供参考】

1)打包用命令或者放到容器中运行

2)用Maven/Gradle插件运行

3)直接执行main方法运行

13、什么是SpringBoot自动配置?

【仅供参考】

Spring和SpringMVC的问题在于需要配置大量的参数。

我们能否带来更多的智能?当一个MVCJAR添加到应用程序中的时候,我们能否自动配置一些

beans?

Spring查看(CLASSPATH上可用的框架)已存在的应用程序的配置。在此基础上,Spring

Boot提供了配置应用程序和框架所需要的基本配置。这就是自动配置。

14、什么是SpringDataREST?

【仅供参考】

SpringDataTEST可以用来发布关于Spring数据库的HATEOASRESTful资源。

15、如何重新加载SpringBoot上的更改,而无需重新启动服务器?

【仅供参考】

这可以使用DEV工具来实现。通过这种依赖关系,您可以节省任何更改,嵌入式tomcat将重新启

动。

SpringBoot有一个开发工具(DevTools)模块,它有助于提高开发人员的生产力。Java开发人

员面临的一个主要挑战是将文件更改自动部署到服务器并自动重启服务器。

开发人员可以重新加载SpringBoot上的更改,而无需重新启动服务器。这将消除每次手动部署

更改的需要。SpringBoot在发布它的第一个版本时没有这个功能。

这是开发人员最需要的功能。DevTools模块完全满足开发人员的需求。该模块将在生产环境中

被禁用。它还提供H2数据库控制台以更好地测试应用程序。

org.springframework,boot

spring-boot-devtools

16、jpa和hibernate有什么区别?

第14/24页

【仅供参考】

jpa全称JavaPersistenceAPI,是Java持久化接口规范,hibernate属于jpa的具体实

现。

17、springboot配置文件有哪几种类型?它们有什么区别?

【仅供参考】

配置文件有.properties格式和.yml格式,它们主要的区别是书法风格不同。

.properties配置如下:

spring.RabbitMQ.port=5672

.yml配置如下:

spring:

RabbitMQ:

port:5672

yml格式不支持@PropertySource注解导入。

18、什么是SpringBootStater?

【仅供参考】

启动器是一套方便的依赖没描述符,它可以放在自己的程序中。你可以一站式的获取你所需要

的Spring和相关技术,而不需要依赖描述符的通过示例代码搜索和复制黏贴的负载。

例如,如果你想使用Sping和JPA访问数据库,只需要你的项目包含spring-boot-starter-

data-jpa依赖项,你就可以完美进行。

19、hibernate有几种查询方式?

【仅供参考】

三种:hql、原生SQL、条件查询Criteria。

20、get()和load。的区别?

【仅供参考】

数据查询时,没有0ID指定的对象,get()返回null;loadO返回一个代理对象。

load。支持延迟加载;get()不支持延迟加载。

四、数据处理篇

1、RabbitMQ集群搭建需要注意哪些问题?

【仅供参考】

各节点之间使用“一link”连接,此属性不能忽略。

各节点使用的erlangcookie值必须相同,此值相当于“秘钥”的功能,用于各节点的认证。

第15/24页

整个集群中必须包含一个磁盘节点。

2、RabbitMQ持久化有什么缺点?

【仅供参考】

持久化的缺地就是降低了服务器的吞吐量,因为使用的是磁盘而非内存存储,从而降低了吞吐

量。可尽量使用ssd硬盘来缓解吞吐量的问题。

3、RabbitMQ中vhost的作用是什么?

【仅供参考】

vhost:每个RabbitMQ都能创建很多vhost,我们称之为虚拟主机,每个虚拟主机其实都是

mini版的RabbitMQ,它拥有自己的队列,交换器和绑定,拥有自己的权限机制。

4、RabbitMQ有几种广播类型?

【仅供参考】

direct(默认方式):最基础最简单的模式,发送方把消息发送给订阅方,如果有多个订阅

者,默认采取轮询的方式进行消息发送。

headers:与direct类似,只是性能很差,此类型几乎用不到。

fanout:分发模式,把消费分发给所有订阅者。

topic:匹配订阅模式,使用正则匹配到消息队列,能匹配到的都能接收到。

5、kafka分布式(不是单机)的情况下,如何保证消息的顺序消费?

【仅供参考】

Kafka分布式的单位是partition,同一个partition用一个writeaheadlog组织,所以可以保

证FIFO的顺序。不同partition之间不能保证顺序。但是绝大多数用户都可以通过messagekey

来定义,因为同一个key的Message可以保证只发送到同一个partition。

Kafka中发送1条消息的时候,可以指定(topic,partition,key)3个参数。partiton和key是

可选的。如果你指定了partition,那就是所有消息发往同1个partition,就是有序的。

并且在消费端,Kafka保证,1个partition只能被1个consumer消费。或者你指定key(比如

orderid),具有同1个key的所有消息,会发往同1个partition。

6、Kafka消息数据积压,消费能力不足怎么处理?

【仅供参考】

1)可以考虑增加Topic的分区数,并且同时提升消费组的消费者数量,消费者数=分区数。(两者

缺一不可)

2)如果是下游的数据处理不及时:提高每批次拉取的数量。批次拉取数据过少(拉取数据/处理

时间〈生产速度),使处理的数据小于生产的数据,也会造成数据积压。

7、为什么要使用kafka,为什么要使用消息队列?

【仅供参考】

缓冲和削峰:上游数据时有突发流量,下游可能扛不住,或者下游没有足够多的机器来保证冗

余,kafka在中间可以起到一个缓冲的作用,把消息暂存在kafka中,下游服务就可以按照自己

第16/24页

的节奏进行慢慢处理。

解耦和扩展性:项目开始的时候,并不能确定具体需求。消息队列可以作为一个接口层,解耦

重要的业务流程。只需要遵守约定,针对数据编程即可获取扩展能力。

冗余:可以采用一对多的方式,一个生产者发布消息,可以被多个订阅topic的服务消费到,供

多个毫无关联的业务使用。

健壮性:消息队列可以堆积请求,所以消费端业务即使短时间死掉,也不会影响主要业务的正

常进行。

异步通信:很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许

用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需

要的时候再去处理它们。

8、zookeeper都有哪些功能?

【仅供参考】

集群管理:监控节点存活状态、运行请求等。

主节点选举:主节点挂掉了之后可以从备用的节点开始新一轮选主,主节点选举说的就是这个

选举的过程,使用zookeeper可以协助完成这个过程。

分布式锁:zookeeper提供两种锁:独占锁、共享锁。独占锁即一次只能有一个线程使用资

源,共享锁是读锁共享,读写互斥,即可以有多线线程同时读同一个资源,如果要使用写锁也

只能有一个线程使用。zookeeper可以对分布式锁进行控制。

命名服务:在分布式系统中,通过使用命名服务,客户端应用能够根据指定名字来获取资源或

服务的地址,提供者等信息。

9、集群中有3台服务器,其中一个节点宕机,这个时候zookeeper还可以使用吗?

【仅供参考】

可以继续使用,单数服务器只要没超过一半的服务器宕机就可以继续使用。

10、说一下zookeeper的通知机制?

【仅供参考】

客户端端会对某个znode建立一个watcher事件,当该znode发生变化时,这些客户端会收

到zookeeper的通知,然后客户端可以根据znode变化来做出业务上的改变。

11、集群中为什么要有主节点?

【仅供参考】

在分布式环境中,有些业务逻辑只需要集群中的某-台机器进行执行,其他的机器可以共享这

个结果,这样可以大大减少重复计算,提高性能,所以就需要主节点。

12、zookeeper有几种部署模式?

【仅供参考】

zookeeper有三种部署模式:

单机部署:一台集群上运行;

集群部署:多台集群运行;

第17/24页

伪集群部署:一台集群启动多个zookeeper实例运行。

13、kafka有几种数据保留的策略?

【仅供参考】

kafka有两种数据保存策略:按照过期时间保留和按照存储的消息大小保留。

14、Kafka中的ISR、AR又代表什么?ISR的伸缩又指什么?

【仅供参考】

ISR:In-SyncReplicas副本同步队列

AR:AssignedReplicas所有副本

ISR是由leader维护,follower从leader同步数据有一些延迟(包括延迟时间

replica,lag.time.max.ms和延迟条数replica,lag.max.messages两个维度,当前最新的版本

0.10.x中只支持replica,lag.time.max.ms这个维度),任意一个超过阈值都会把follower剔除

出ISR,存入OSR(Outof-SyncReplicas)列表,新加入的follower也会先存放在OSR中。

AR=ISR+0SRo

15、使用kafka集群需要注意什么?

【仅供参考】

集群的数量不是越多越好,最好不要超过7个,因为节点越多,消息复制需要的时间就越长,

整个群组的吞吐量就越低。

集群数量最好是单数,因为超过一半故障集群就不能用了,设置为单数容错率更高。

16、Redis淘汰策略有哪些?

【仅供参考】

volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用

的数据淘汰。

volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数

据淘汰。

volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘

汰。

allkeys-lru:从数据集(server.db[i].diet)中挑选最近最少使用的数据淘汰。

allkeys-random:从数据集(server.db[i].diet)中任意选择数据淘汰。

no-enviction(驱逐):禁止驱逐数据。

17、什么是缓存穿透?怎么解决?

【仅供参考】

缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数

据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。

解决方案:最简单粗暴的方法如果一个查询返回的数据为空(不管是数据不存在,还是系统故

障),我们就把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

第18/24页

18、jedis和Redisson有哪些区别?

【仅供参考】

jedis:提供了比较全面的Redis命令的支持。

Redisson:实现了分布式和可扩展的Java数据结构,与jedis相比Redisson的功能相对简

单,不支持排序、事务、管道、分区等Redis特性。

19、Redis为什么是单线程的?

【仅供参考】

因为cpu不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存或者网络带宽。既然单线程

容易实现,而且cpu又不会成为瓶颈,那就顺理成章地采用单线程的方案了。

关于Redis的性能,官方网站也有,普通笔记本轻松处理每秒几十万的请求。

而且单线程并不代表就慢nginx和nodejs也都是高性能单线程的代表。

20、Redis是什么?都有哪些使用场景?

【仅供参考】

Redis是一个使用C语言开发的高速缓存数据库。

Redis使用场景:

记录帖子点赞数、点击数、评论数;

缓存近期热帖;

缓存文章详情信息;

记录用户会话信息。

五、MySQL数据库篇

1、InnoDB为什么设计B+树索引?

【仅供参考】

两个考虑因素:

InnoDB需要执行的场景和功能需要在特定查询上拥有较强的性能。

CPU将磁盘上的数据加载到内存中需要花费大量时间。

为什么选择B+树:

哈希索引虽然能提供0(1)复杂度查询,但对范围查询和排序却无法很好的支持,最终会导致

全表扫描。

B树能够在非叶子节点存储数据,但会导致在查询连续数据可能带来更多的随机10。

而B+树的所有叶节点可以通过指针来相互连接,减少顺序遍历带来的随机10。

普通索引还是唯一索引?

由于唯一索引用不上changebuffer的优化机制,因此如果业务可以接受,从性能角度出发建

议你优先考虑非唯一索引。

2、说一下乐观锁和悲观锁?

第19/24页

【仅供参考】

乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会

判断一下在此期间别人有没有去更新这个数据。

悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别

人想拿这个数据就会阻止,直到这个锁被释放。

数据库的乐观锁需要自己实现,在表里面添加一个version字段,每次修改成功值加1,这样

每次修改的时候先对比一下,自己拥有的version和数据库现在的version是否一致,如果

不一致就不修改,这样就实现了乐观锁。

3、如何获取当前数据库版本?

【仅供参考】

使用selectversion()获取当前MySQL数据库版本。

4、MySQL问题排查都有哪些手段?

【仅供参考】

使用showprocesslist命令查看当前所有连接信息。

使用explain命令查询SQL语句执行计划。

开启慢查询日志,查看慢查询的SQLO

5、要不要使用分区表?

【仅供参考】

分区并不是越细越好。实际上,单表或者单分区的数据一千万行,只要没有特别大的索引,对

于现在的硬件能力来说都已经是小表了。

分区也不要提前预留太多,在使用之前预先创建即可。比如,如果是按月分区,每年年底时再

把下一年度的12个新分区创建上即可。对于没有数据的历史分区,要及时的drop掉。

6、什么是WAL技术,有什么优点?

【仅供参考】

WAL,中文全称是Write-AheadLogging,它的关键点就是日志先写内存,再写磁盘。MySQL执

行更新操作后,在真正把数据写入到磁盘前,先记录日志。

好处是不用每一次操作都实时把数据写盘,就算crash后也可以通过redolog恢复,所以能

够实现快速响应SQL语句。

7、一张自增表里面总共有7条数据,删除了最后2条数据,重启MySQL数据库,又插入了

一条数据,此时id是几?

【仅供参考】

表类型如果是MyISAM,那id就是8。

表类型如果是InnoDB,那id就是6。

InnoDB表只会把自增主键的最大id记录在内存中,所以重启之后会导致最大id丢失。

8、MySQL的changebuffer是什么?

第20/24页

【仅供参考】

当需要更新一个数据页时,如果数据页在内存中就直接更新;而如果这个数据页还没有在内存

中的话,在不影响数据一致性的前提下,InnoDB会将这些更新操作缓存在changebuffer

中。

这样就不需要从磁盘中读入这个数据页了,在下次查询需要访问这个数据页的时候,将数据页

读入内存,然后执行changebuffer中与这个页有关的操作。通过这种方式就能保证这个数据

逻辑的正确性。

注意唯一索引的更新就不能使用changebuffer,实际上也只有普通索引可以使用。

适用场景:

-对于写多读少的业务来说,页面在写完以后马上被访问到的概率比较小,此时change

buffer的使用效果最好。这种业务模型常见的就是账单类、日志类的系统。

-反过来,假设一个业务的更新模式是写入之后马上会做查询,那么即使满足了条件,将更新

先记录在changebuffer,但之后由于马上要访问这个数据页,会立即触发merge过程。这样

随机访问10的次数不会减少,反而增加了changebuffer的维护代价。

9、为什么删除了表,表文件的大小还是没变?

【仅供参考】

数据项删除之后InnoDB某个页pageA会被标记为可复用。

delete命令把整个表的数据删除,结果就是,所有的数据页都会被标记为可复用。但是磁盘

上,文件不会变小。

经过大量增删改的表,都是可能是存在空洞的。这些空洞也占空间所以,如果能够把这些空洞

去掉,就能达到收缩表空间的目的。

重建表,就可以达到这样的目的。可以使用altertableAengine=InnoDB命令来重建表。

10、主库出问题如何解决?

【仅供参考】

基于位点的主备切换:存在找同步位点这个问题

MySQL5.6版本引入了GTID,彻底解决了这个困难。那么,GTID到底是什么意思,又是如何

解决找同步位点这个问题呢?

GTID:全局事务ID,是一个事务在提交的时候生成的,是这个事务的唯一标识;它由两部分组

成,格式是:GTID=server_uuid:gno

每个MySQL实例都维护了一个GTID集合,用来对应“这个实例执行过的所有事务”。

在基于GTID的主备关系里,系统认为只要建立主备关系,就必须保证主库发给备库的日志是

完整的。因此,如果实例B需要的日志已经不存在,A'就拒绝把日志发给Bo

11、grant和flushprivileges语句?

【仅供参考】

grant语句会同时修改数据表和内存,判断权限的时候使用的内存数据,因此,规范使用是不需

要加上flushprivileges语句。

flushprivileges语句本身会用数据表的数据重建一份内存权限数据,所以在权限数据可能存

在不一致的情况下再使用。

第21/24页

12、说一下MySQL常用的引擎?

【仅供参考】

InnoDB引擎:mysql5.1后默认的数据库引擎,提供了对数据库acid事务的支持,并且还提

供了行级锁和外键的约束,它的设计的目标就是处理大数据容量的数据库系统。MySQL运行的

时候,InnoDB会在内存中建立缓冲池,用于缓冲数据和索引。但是该引擎是不支持全文搜索,

同时启动也比较的慢,它是不会保存表的行数的,所以当进行selectcount(*)fromtable

指令的时候,需要进行扫描全表。由于锁的粒度小,写操作是不会锁定全表的,所以在并发度较

高的场景下使用会提升效率的。

MylASM引擎:不提供事务的支持,也不支持行级锁和外键。因此当执行插入和更新语句时,即

执行写操作的时候需要锁定这个表,所以会导致效率会降低。不过和InnoDB不同的

是,MylASM引擎是保存了表的行数,于是当进行se

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论