java面试题整理

1、基础

1.1、面向对象都有那些特征、拼简单说明各个特征的内容

继承、多态、封装、抽象

1、继承、是使用已存在的类的定义,作为建立新类的基础技术,新类可以增加新的属性或新的方法,也可以用父类的功能,但不能选择性地继承。通过使用继承,能够非常方便地复用这些代码。

2、封装、把对象的属性私有化,同时提供可以被外界访问这些属性的方法。(如果属性不想被外界访问,那大可不必提供方法给外界访问;但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了)

3、多态、就是一个事物拥有不同形式的能力。表现为程序中定义的引用变量,所指向的具体类型和具体调用的方法,在编译期并不能确定,而是在程序运行期确定。

4、抽象、忽略与当前主题目标无关的那些方面,以便更充分地注意到与当前目标有关的方。

1.2、在java中、String是基础数据类型吗?请写出 java的所有数据类型

不是、String是引用类型, char int long short double float boolean byte

1.3、String和StirngBuffer区别

String 是不可变的字符序列 StringBuffer是可变的字符序列、效率低,线程安全

1.4、final、finally、finalizs的区别

final 可以用来修饰变量、方法、类

     finally异常处理关键字,finally中的主体总会执行,不管异常发生是否。

finalizs 类的Finalize方法,可以告诉垃圾回收器应该执行的操作,该方法从Object类继承而来。

1.5、Overload和Override的区别、Overloaded的方法是否可以改变返回值的类型

Overload重载、同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同

Override重写、表示子类中的方法可以与父类中的某个方法的名称和参数完全相同

不可以,温馨提醒:方法重载必须保证方法的传入参数不同哦。

1.6、error和exception有什么区别

Error类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和预防,遇到这样的错误,建议让程序终止。

Exception类表示程序可以处理的异常,可以捕获且可能恢复。遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常。

ArrayIndexOutOfBoundsException 数组下标越界异常,

ArithmaticException 算数异常 如除数为零

NullPointerException 空指针异常

IllegalArgumentException 不合法参数异常

1.7、abstract class 和 interface 有什么区别

interface需要实现,要用implements,而abstract class需要继承,要用extends。

一个类可以实现多个interface,但是一个类只能继承一个abstract class。

 interface强调特定功能的实现,而abstract class强调所属关系。
 ​
 尽管interface实现类及abstract class的子类都必须要实现相应的抽象方法,但实现的形式不同,interface中的每一个方法都是抽象方法(JDK1.8以后在接口中使用default和static关键字来修饰接口中定义的普通方法),都只是声明的(declaration,没有方法体),实现类必须要实现。而abstract class的子类可以有选择地实现。

1.8、GC是什么?为什么要有GC

GC是垃圾收集的意思,内存处理是开发人员容易出现问题的地方,忘记或者错误地内存回收会导致程序或者系统的不稳定甚至崩溃,Java提供的垃圾回收机制可以自动检测对象是否超过作用域从而达到自动回收的目的。

1.9、是否可以继承String类,为什么?

不能被继承,因为String类有final修饰符,而final修饰的类是不能被继承的。

1.20、char型变量中能不能存贮一个中文汉字?为什么

unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。

1.21、一个java源文件中是否可以包含多个类(不是内部类),有什么限制?

可以有多个类,但是只能有一个public的类,并且public的类名必须与文件名相一致。

1.22、什么是java序列化?如何实现java序列化

序列化:将 Java 对象转换成字节流的过程。

类实现 Serializable 接口,这个接口没有需要实现的方法。实现 Serializable 接口是为了告诉 jvm 这个类的对象可以被序列化。

1.23、CAS 乐观锁机制

独占锁是一种悲观锁,而 synchronized 就是一种独占锁,synchronized 会导致其它所有未持有锁的线程阻塞,而等待持有锁的线程释放锁。

所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。而乐观锁用到的机制就是CAS。compare and swap

CAS、是比较交换的意思、每一个线程过来都会把主内存中的值复制到一份放到自己的内存中,每次修改的时候都去判断主内存中值是否跟自己的期望值一样、一样就修改、否则就不修改。

1.24、forward和redirect的区别?

forward又叫转发,redirect叫做重定向。

forword是服务器内部的重定向,服务器直接访问目标地址的 url网址,把里面的东西读取出来,但是客户端并不知道,因此用forward的话,客户端浏览器的网址是不会发生变化的。

redirect是服务器根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,所以地址栏显示的是新的地址。

1.25、说出数据连接池的工作机制是什么?

数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。

连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。

1.26、JSP的内置对象有哪些?并简单说明作用?

request:封装客户端的请求,其中包含来自GET或POST请求的参数;

response:封装服务器对客户端的响应;

pageContext:通过该对象可以获取其他对象;

session:封装用户会话的对象;

application:封装服务器运行环境的对象;

out:输出服务器响应的输出流对象;

config:Web应用的配置对象;

page:JSP页面本身(相当于Java程序中的this);

exception:封装页面抛出异常的对象。

1.27、什么情况下调用doGet,dopost?

前台form是get 就doGet 前台是post就是doPost 。详细一点就是比如你页面上一个form。<form method="get" action="yourServlet">form内容</form>。然后你提交这个form后 到yourServlet这个servlet后就在doGet()方法里有form提交过来的数据 在这个方法里对他进行处理。post也一样了。

get和post是请求方式。一般get携带的信息量有限制,而且他的内容会在显示栏里面出现,不安全。post可携带大量数据,并且信息不会出现在显示栏里比较安全。当实现查询功能时适合用get。get效率比post高些。

1.28、JSP和Servlet有那些相同点和不同点、他们之间的联系是什么?

相同点:JSP和Servlet本质上都是Java类。

不同点:JSP侧重于视图,Servlet主要用于控制逻辑 Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及?HttpServlet对象获得。

联 系:JSP是Servlet技术的扩展,本质上就是Servlet的简易方式。

1.29、XML文档定义的几种形式,它们之间有何本质区别,解析xml文档有哪几种方式。

XML文档定义分为DTD文档类型定义和Schema两种形式

schema 本身是 xml 的,可以被 XML 解析器解析(这也是从 DTD)

有 DOM,SAX,STAX 等;

DOM解析:?DOM的全称是Document Object Model,也即文档对象模型。在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程序正是通过对这个对象模型的操作,来实现对XML文档数据的操作。通过DOM接口,应用程序可以在任何时候访问XML文档中的任何一部分数据,因此,这种利用DOM接口的机制也被称作随机访问机制。

SAX解析:SAX的全称是Simple APIs for XML,也即XML简单应用程序接口。与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式。当使用SAX分析器对XML文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而SAX接口也被称作事件驱动接口。

JDOM解析:JDOM采用了Java中的Collection架构来封装集合,是Java爱好者更加熟悉的模式

DOM4J解析:xml解析器一次性把整个xml文档加载进内存,然后在内存中构建一颗Document的对象树,通过Document对象,得到树上的节点对象,通过节点对象访问(操作)到xml文档的内容

1.30、BS和CS的联系与区别

1、处理问题不同

C/S 程序可以处理用户面固定, 并且在相同区域,安全要求高需求,与操作系统相关。应该都是相同的系统。

B/S 建立在广域网上,面向不同的用户群,分散地域,这是C/S无法作到的。与操作系统平台关系最小。

2、用户接口不同

C/S 多是建立的Window平台上,表现方法有限,对程序员普遍要求较高。

B/S 建立在浏览器上,有更加丰富和生动的表现方式与用户交流。并且大部分难度减低,减低开发成本。

3、信息流不同

C/S 程序一般是典型的中央集权的机械式处理,交互性相对低。

B/S 信息流向可变化,B-B B-C B-G等信息、流向的变化,更像交易中心。

联系:系统开发中C/S结构(Client/Server)中Client(客户端)往往可以由 B/S结构(Browser/Server结构)的Browser(浏览器)及其载体承担。

C/S结构的Web应用与B/S结构(Browser/Server结构)具有紧密联系。大系统和复杂系统中,C/S结构和B/S结构的嵌套也很普遍。

1.40、描述一下http协议的特点,并说明为什么?

1.支持 客户/服务器模式。

\2. 简单、快速

即:客户向服务器请求服务时,只需传送请求方法和路径

\3. 允许传输任意类型的数据对象,具有灵活性。

\4. 无连接(请求时连接,请求完释放连接,以尽快将资源释放出来服务其他客户端)

无连接指的是 限制每次连接只处理一个请求。

服务器处理完客户的请求,并收到客户端的应答后,即断开连接;采用这种方式可以节省时间。

5.无状态 (每个请求都是独立的)

HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

1.41、写出STRUTS中主要用到的部分?

  1. Model 部分

  2. View 部分

  3. Controller部分

1.42、写一个Singleton出来

public class Singleton {

private static Singleton instance = null;

private Singleton() {};

public static Singleton getInstance() {

if(instance == null) {

synchronized(Singleton.class) {

if(instance == null) {

instance = new Singleton();

}

}

}

return instance;

}

}

1.43、存储过程和函数的区别

1、存储过程是SQL语句和可选控制流语句的预编译集合,而函数是由一个或多个 SQL 语句组成的子程序;2、存储过程可以在单个存储过程中执行一系列SQL语句,而自定义函数有诸多限制;3、执行方式不同。

1、存储过程:存储过程是SQL 语句和可选控制流语句的预编译集合,以一个名称存储并作为一个单元处理。

2、函数:是由一个或多个 SQL 语句组成的子程序,可用于封装代码以便重新使用。 函数限制比较多,如不能用临时表,只能用表变量等

1、存储过程:可以在单个存储过程中执行一系列 SQL 语句。而且可以从自己的存储过程内引用其它存储过程,这可以简化一系列复杂语句。

2、函数:自定义函数诸多限制,有许多语句不能使用,许多功能不能实现。函数可以直接引用返回值,用表变量返回记录集。但是,用户定义函数不能用于执行一组修改全局数据库状态的操作。

1、存储过程:存储过程可以返回参数,如记录集,函数只能返回值或者表对象。存储过程的参数有in,out,inout三种,存储过程声明时不需要返回类型。

2、函数:函数参数只有in,而函数需要描述返回类型,且函数中必须包含一个有效的return语句。

1.44、什么是事务

事务一般而言是相对数据库而言的,对于数据库一次操作就属于一个事务,

一次操作可以是几句sql语句,也可以是几句JDBC的Java语句。

一次操作的成败直接影响数据库的数据以及与被修改数据有关的数据。所以,事务相当重要。

是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合(工作逻辑单元);

事务的四大特性:

1 、原子性

事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做

2 、一致性

事 务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统 运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是 不一致的状态。

3 、隔离性

一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。

4 、持续性

也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响

1.45、请列出你见过的服务器响应状态码并解释其意义

200 OK //客户端请求成功

400 Bad Request //客户端请求有语法错误,不能被服务器所理解

401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用

403 Forbidden //服务器收到请求,但是拒绝提供服务

404 Not Found //请求资源不存在,eg:输入了错误的URL

500 Internal Server Error //服务器发生不可预期的错误

503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常

2开头 (成功响应)表示成功处理了请求的状态码 200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。 201 (已创建) 请求成功并且服务器创建了新的资源。 202 (已接受) 服务器已接受请求,但尚未处理。 203 (非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。 204 (无内容) 服务器成功处理了请求,但没有返回任何内容。 205 (重置内容) 服务器成功处理了请求,但没有返回任何内容。 206 (部分内容) 服务器成功处理了部分 GET 请求。 3开头 (请求被重定向)表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。 300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。 301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。 302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。 303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。 304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。 305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。 307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。 4开头 (请求错误)这些状态代码表示请求可能出错,妨碍了服务器的处理。 400 (错误请求) 服务器不理解请求的语法。 401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。 403 (禁止) 服务器拒绝请求。 404 (未找到) 服务器找不到请求的网页。 405 (方法禁用) 禁用请求中指定的方法。 406 (不接受) 无法使用请求的内容特性响应请求的网页。 407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。 408 (请求超时) 服务器等候请求时发生超时。 409 (冲突) 服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。 410 (已删除) 如果请求的资源已永久删除,服务器就会返回此响应。 411 (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。 412 (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。 413 (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。 414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。 415 (不支持的媒体类型) 请求的格式不受请求页面的支持。 416 (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。 417 (未满足期望值) 服务器未满足"期望"请求标头字段的要求。 5开头(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。 500 (服务器内部错误) 服务器遇到错误,无法完成请求。 501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。 502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。

1.46、请写出遍历map的方法

Map<String, String> map = new HashMap<String, String>();

1、 for (String key : map.keySet()) {

System.out.println("key= "+ key + " and value= " + map.get(key));

}

2、Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();

while (it.hasNext()) {

Map.Entry<String, String> entry = it.next();

System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());

}

3、 System.out.println("通过Map.entrySet遍历key和value");

for (Map.Entry<String, String> entry : map.entrySet()) {

System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());

}

1.47、请将数组进行升序排序

利用Arrays中的sort()方法将数组中的元素进行升序排列

1.48、将文件复制到另一个目录下

1、private static void copyFileUsingApacheCommonsIO(File source, File dest) throws IOException {

FileUtils.copyFile(source, dest);

}

2、private static void copyFileUsingJava7Files(File source, File dest) throws IOException {

Files.copy(source.toPath(), dest.toPath());

}

1.49、jvm垃圾回收机制,gc发生在Jvm哪部分,有几种gc,它们的算法是什么

1、在heap部分,有Minor GC,Full GC,

2、Minor GC 复制算法(copying)

3、Full GC 标记清除(Mark-Sweep),标记压缩(Mark-Compact)

1.52、线程也具有生命周期,主要包括 7 种状态

分别是出生状态、就绪状态、运行状态、等待状态、休眠状态、阻塞状态和死亡状态

1.54、5个异常问题

java.util.concurrentModificationException 并发修改异常

java.lang.stackOverflowError 深度的调用导致栈满了,报错误

java.lang.outOfMenoryError java heap space 堆内存不够用了。

java.lang.nullpointerexception 解释是"程序遇上了空指针

FileNotFoundException 解释是“文件未找到异常”

1.55、jpa使用过吗

JPA 是一个基于O/R映射的标准规范、

JPA 的主要实现有Hibernate、EclipseLink 和OpenJPA 等

1.56、servlet生命周期

Servlet 初始化后调用 init () 方法。

Servlet 调用 service() 方法来处理客户端的请求。

Servlet 销毁前调用 destroy() 方法。

最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

Servlet 加载--->实例化--->服务--->销毁。

1.57、java中的io流分几种

按照功能:输入流(input)、输出流(output)

按照类型区分:字节流跟字符流

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

1.58、BIO、NIO、AIO、有什么区别

BIO、Block IO同步堵塞式IO、就是我们平常使用的传统IO,他的特点是模式简单使用方便。

NIO、New IO 同步非堵塞式IO、是传统的BIO升级,客户端跟服务端通过Channel通道通讯,实现多路复用

AIO、Asynchronous IO 异步非堵塞式lO、是NIO的升级、异步IO的操作基于事件和回调机制。

1.59、java 死锁如何避免

造成死锁的几个原因 1、一个资源每次只能被一个线程使用 2、一个线程在阻塞等待某个资源时、不释放已占有资源 3、一个线程已经获得的资源、在未使用完之前,不能被强行剥夺 4、若干线程形成头尾相接的循环等待资源关系 这是造成死锁必要达到的4个条件、如果要避免死锁,自需要不满足其中某一个条件即可,其中前3个条件是作为锁要符合的条件,所以要避免死锁就需要打破第4个条件

1.60、泛型中extends和super的区别

1、<? extends T> 表示包括T在内的任何T的子类 2、<? super T>表示包括T在内的任何T的父类

1.61、二叉搜索树和平衡二叉树有什么关系

平衡二叉树也叫平衡二叉搜索树、是二叉搜索树的升级版、二叉搜索树是指节点左边的所有节点都比该节点小,节点右边的节点都比该节点大。 而平衡二叉搜索树是在二叉搜索的基础上还规定了节点左右两边的子树高度差的绝对值不能超过1

1.61、并发编程的三要素

1、原子性、不可分割的操作、多个步骤要保证同时成功或者同时失败 2、有序性、程序执行的顺序和代码的顺序保持一致。 3、可用性、一个线程对共享变量的修改、另一个线程能立马看到

1.62、强平衡二叉树和弱平衡二叉树有什么区别

强平衡二叉树AVL树、弱平衡二叉树就是我们说的红黑树 1、AVL树比红黑树对于平衡的程度更加严格,在相同节点的情况下,AVL树的高度低于红黑树 2、红黑树中增加了一个节点颜色的概念 3、AVL树的旋转操作比红黑树的旋转操作更耗时

1.63、B+树的特点

1、拥有B树的特点, 2、叶子节点之间有指针 3、非叶子节点上的元素在叶子节点上都沉余了,也就是叶子节点中存存储了所有的元素,并且排好顺序。 Mysql索引使用的是B+树、因为索引是用来加快查询的,而B+树通过对数据进行排序所以是可以提高查询速度的,然后通过一个节点中可以存储多个元素,从而可以使得B+树得高度不会太高, 在Mysql中一个innodb页就是一个B+树节点,一个innodb页默认16kb,所以一般情况下一颗两层的B+树可以存2000万行左右的数据,然后通过利用B+树叶子节点存储了素有数据并且进行了排序, 并且叶子节点之间有指针、可以很好的支持全表扫描,范围查找等SQL语句

1.64、threadlocal是什么

threadlocal而是一个线程内部的存储类,可以在指定线程内存储数据,数据存储以后,只有指定线程可以得到存储数据,大致意思就是ThreadLocal提供了线程内存储变量的能力,这些变量不同之处在于每一个线程读取的变量是对应的互相独立的。通过get和set方法就可以得到当前线程对应的值。

2、深入

2.1、sysnchronized 升级过程

1、在代码进入同步块的时候,如果同步对象锁状态为无锁状态(锁标志位为“01”状态,是否为偏向锁为“0”),虚拟机首先将在当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间,用于存储锁对象目前的Mark Word的拷贝,官方称之为 Displaced Mark Word。 ​ 2、当多个线程竞争时(竞争的线程不多),以CAS的方式修改MarkWord 谁修改成功了就算谁的类似数据库的乐观锁(乐观锁有版本号,而自旋锁是比较操作的值,存在ABA问题)指向线程栈中的LockRecord,记录了线程被锁住多少次(Syn是可重入锁) ​ 3、重量锁:其他线程都进队列等着(等待队列),不需要在那里转,占用CPU资源了

2.2、JDK8的新特性

default关键字、Lambda表达式、函数式接口、Date Api更新 

//无参无返回 NoReturnNoParam noReturnNoParam = () -> { System.out.println("NoReturnNoParam"); }; noReturnNoParam.method();

//一个参数无返回 NoReturnOneParam noReturnOneParam = (int a) -> { System.out.println("NoReturnOneParam param:" + a); }; noReturnOneParam.method(6);

//多个参数无返回 NoReturnMultiParam noReturnMultiParam = (int a, int b) -> { System.out.println("NoReturnMultiParam param:" + "{" + a +"," + + b +"}"); }; noReturnMultiParam.method(6, 8);

//无参有返回值 ReturnNoParam returnNoParam = () -> { System.out.print("ReturnNoParam"); return 1; }; int res = returnNoParam.method(); System.out.println("return:" + res);

//一个参数有返回值 ReturnOneParam returnOneParam = (int a) -> { System.out.println("ReturnOneParam param:" + a); return 1; }; int res2 = returnOneParam.method(6); System.out.println("return:" + res2);

//多个参数有返回值 ReturnMultiParam returnMultiParam = (int a, int b) -> { System.out.println("ReturnMultiParam param:" + "{" + a + "," + b +"}"); return 1; };

Stream、

2.3、请谈谈你对volatile的理解

1.1、 volatile是java虚拟机提供的轻量级的同步机制

1.1.1、保证可见性、不保证原子性、禁止指令重排

1.2、 jmm你谈谈

1.2.1、可见性、原子性、有序性

VolatileDemo代码演示可见性+原子性代码

线程安全性获得保证

1.3、 你在哪些地方用到过volatile

在多线程中为了保证变量的可见性、可以使用volatile修饰变量

2.4、什么是CAS

2.1、比较并交换 atomicInteger.compareAndSet

2.2、底层实现原理

2.3、缺点、循环时间常开销大,只能保证一个共享变量原子操作,引出来ABA问题,

static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);

static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100, 1);

2.5、讲一讲Atomiclnteger,为什么要用CAS而不是synchronized

A.synchronized采用的是悲观锁,是一种独占锁,独占锁就意味着 其他线程只能依靠阻塞[就是其他线程不停的询问]来等待线程释放锁。而在 CPU 转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起 CPU 频繁的上下文切换导致效率很低 B.CAS采用的是一种乐观锁的机制,它不会阻塞任何线程,所以在效率上,它会比 synchronized 要高。所谓乐观锁就是:每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。

2.6、Java常用的设计模式

1、 单例模式、系统中创建一个共享资源对象。

2、 工厂模式、就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建

3、 观察者模式、其实就是发布订阅模式,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。

4、 装饰器设计模式、装饰模式在不改变原先核心功能的情况下,可以实现增强,并且不会产生很多继承类,按照业务模块划分,通过不同的方法进行装饰。

2.7、类加载器

1.装载。(根据查找路径找到相对应的calss文件,然后导入。)

2.链接 (链接又分为3个小步骤:1。检查:检查待加载的class文件的正确性。2。准备:给类中的静态变量分配存储空间。3。解析:将符号引用转换成直接引用.)

3.初始化。(对静态变量和静态代码块执行初始化工作。)

2.8、类加载过程

类加载过程主要包含加载、验证、准备、解析、初始化、使用、卸载七个方面,下面一一阐述。

1、加载

在加载阶段,虚拟机主要完成三件事:

1.通过一个类的全限定名来获取定义此类的二进制字节流。

2.将这个字节流所代表的静态存储结构转化为方法区域的运行时数据结构。

3.在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区域数据的访问入口

2、验证

验证阶段作用是保证Class文件的字节流包含的信息符合JVM规范,不会给JVM造成危害。如果验证失败,就会抛出一个java.lang.VerifyError异常或其子类异常。验证过程分为四个阶段

1.文件格式验证:验证字节流文件是否符合Class文件格式的规范,并且能被当前虚拟机正确的处理。

2.元数据验证:是对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言的规范。

3.字节码验证:主要是进行数据流和控制流的分析,保证被校验类的方法在运行时不会危害虚拟机。

4.符号引用验证:符号引用验证发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在解析阶段中发生。

3、准备

准备阶段为变量分配内存并设置类变量的初始化。在这个阶段分配的仅为类的变量(static修饰的变量),而不包括类的实例变量。对已非final的变量,JVM会将其设置成"零值",而不是其赋值语句的值:

pirvate static int size = 12;

那么在这个阶段,size的值为0,而不是12。 final修饰的类变量将会赋值成真实的值。

4、解析

解析过程是将常量池内的符号引用替换成直接引用。主要包括四种类型引用的解析。类或接口的解析、字段解析、方法解析、接口方法解析。

5、初始化

在准备阶段,类变量已经经过一次初始化了,在这个阶段,则是根据程序员通过程序制定的计划去初始化类的变量和其他资源。这些资源有static{}块,构造函数,父类的初始化等。

至于使用和卸载阶段阶段,这里不再过多说明,使用过程就是根据程序定义的行为执行,卸载由GC完成。

2.9、什么是双亲委派

当一个类加载器收到类加载任务时,立即将任务委派给它的父类加载器去执行,直至委派给最顶层的启动类加载器为止。如果父类加载器无法加载委派给它的类时,将类加载任务退回给它的下一级加载器去执行; 除了启动类加载器以外,每个类加载器拥有一个父类加载器,用户的自定义类加载器的父类加载器是AppClassLoader; 双亲委派模型可以保证全限名指定的类,只被加载一次; 双亲委派模型不具有强制性约束,是Java设计者推荐的类加载器实现方式;

2.10、sysnchronized 和reentrantLock 的区别

1、synchronized 是JVM层面的锁,是Java关键字。ReentrantLock 是从jdk1.5以来(java.util.concurrent.locks.Lock)提供的API层面的锁

2、synchronized 不需要用户去手动释放锁,synchronized 代码执行完后系统会自动让线程释放对锁的占用; ReentrantLock则需要用户去手动释放锁,如果没有手动释放锁,就可能导致死锁现象。一般通过lock()和unlock()方法配合try/finally语句块来完成,使用释放更加灵活。

3、synchronized是不可中断类型的锁,除非加锁的代码中出现异常或正常执行完成; ReentrantLock则可以中断,可通过trylock(long timeout,TimeUnit unit)设置超时方法或者将lockInterruptibly()放到代码块中,调用interrupt方法进行中断。

4、synchronized为非公平锁 ReentrantLock则即可以选公平锁也可以选非公平锁,通过构造方法new ReentrantLock时传入boolean值进行选择,为空默认false非公平锁,true为公平锁。

5、锁是否可绑定条件Condition、synchronized不能绑定; ReentrantLock通过绑定Condition结合await()/singal()方法实现线程的精确唤醒,而不是像synchronized通过Object类的wait()/notify()/notifyAll()方法要么随机唤醒一个线程要么唤醒全部线程。

6、synchronzied锁的是对象,锁是保存在对象头里面的,根据对象头数据来标识是否有线程获得锁/争抢锁;ReentrantLock锁的是线程,根据进入的线程和int类型的state标识锁的获得/争抢。

1、sychronized 是一个关键字、ReentrantLock是一个类 2、sychronized 会自动的加锁与释放锁、ReentrantLock需要程序员手动加锁与释放锁 3、sychronized的底层是JVM底层的锁、ReentrantLock是API层面的锁 4、sychronized是非公平锁,ReentrantLock可以选择公平或非公平 5、sychronized锁的是对象,锁信息保存在对象头中,ReentrantLock通过代码中int类型的state标识来标识锁的状态 6、sychronized底层有一个锁升级的过程。

2.11、TCP 他的 keepalive机制了解过吗

建立 TCP -> 请求资源 -> 响应资源 -> 释放连接,那么此方式就是 HTTP 短连接

tcp是面向连接、UDP是无连接的、即发送数据之前不需要建立连接、一般数据传输要求安全性高完整性的都要用TCP协议、UDP比如视频通话。

2.12、说说类加载器双亲委派模型

jvm中存在三个默认的类加载器 1、BootStrapClassLoader 2、ExtClassLoader 3、AppClassLoader AppClassLoader的父加载器是ExtClassLoader,ExtClassLoader的父加载器是BootstrapClassLoader Jvm在加载一个类时、会调用AppClassLoader的loadClass方法来加载这个类,不过在这个方法中,会先使用ExtClassLoader的loadClass方法来加载类,同样ExtClassLoader的loadClass方法中会先使用BootstrapClassLoader来加载类,如果BootstrapClassLoader加载到了就直接成功,如果BootstrapClassLoader没有加载到,那么ExtClassLoader就会自己尝试加载该类,如果没有加载到,那么则会由AppClassLoader来加载这个类。 所以、双亲委派指的是、JVM在加载类时,会委派给Ext和Bootstrap进行加载,如果没加载到才由自己进行加载。

启动类加载器 Bootstrap ClassLoader 扩展类加载器 Extension ClassLoader 应用程序类加载器 Application ClassLoader

2.13、sychronized的自旋锁、偏向锁、轻量级锁、重量级锁、分别介绍和联系

1、偏向锁、在锁对象的对象头中记录一下当前获取到该锁的线程ID、该线程下次如果又来获取该锁就可以直接获取到了, 2、轻量级锁,由偏向锁升级而来,当一个线程获取到锁后,此时这把锁是偏向锁,此时如果有第二个线程来竞争锁,偏向锁就会升级轻量级锁,之所以叫轻量级锁,是为了和重量级锁区分开来,轻量级锁底层是通过自旋来实现的,并不会阻塞线程。 3、如果自旋次数过多仍然没获取到锁,则会升级为重量级锁,重量级锁会导致线程阻塞 4、自旋锁、自旋锁就是线程在获取锁的过程中,不会去阻塞线程,也就无所谓唤醒线程,阻塞和唤醒这两个步骤都是需要操作系统进行的,比较消耗时间,自旋锁是线程通过CAS获取预期的一个标记,如果没有获取到,则继续循环获取,如果获取到了则表示获取到了锁,这个过程线程一直在运行中,相对而言没有使用太多的操作系统资源,比较轻量。

3、Collection集合

3.1、list set map

1、List是一个继承于Collection的接口,即List是集合中的一种。List是有序的队列,List中的每一个元素都有一个索引;第一个元素的索引值是0,往后的元素的索引值依次+1。和Set不同,List中允许有重复的元素。实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。list 是有序的,允许重复。

1.1、ArrayList底层数据结构:数组型,查询快、增删慢,线程不安全。

ArrayList是一个动态数组,也是我们常用的集合,它允许任何元素的插入,甚至包括null。每一个ArrayList都有一个初始化的容量(10),该容量代表了数组的大小,随着容器中容量的不断增加,容器的大小也会随着增加。在每次向容器中增加元素时,会进行容量检查,当快溢出时,会进行扩容操作。

允许插入的元素重复、插入的元素是有序的、动态扩容、非线程安全,异步、基于动态数组的数据结构、擅长随机访问(get set)。

1.2、LinkedList底层数据结构:链表型,增删快、查询慢,线程不安全。

基于双端链表,添加/删除元素只会影响周围的两个节点,开销很低;只能顺序遍历,无法按照索引获得元素,因此查询效率不高;没有固定容量,不需要扩容;需要更多的内存, LinkedList 每个节点中需要多存储前后节点的信息,占用空间更多些。

1.3、Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。Vectorr实际上是通过一个数组去保存数据的。当我们构造Vecotr时;若使用默认构造函数,则Vector的默认容量大小是10

2、Set是一个继承于Collection的接口,Set是一种不包括重复元素的Collection。它维持它自己的内部排序,所以随机访问没有任何意义。与List一样,它同样运行null的存在但是仅有一个。由于Set接口的特殊性,所有传入Set集合中的元素都必须不同,关于API方面。Set的API和Collection完全一样。实现了Set接口的集合有:HashSet、TreeSet、LinkedHashSet、EnumSet。set是无序的,不允许重复。

2.1、HashSet实现了Set接口,即它不允许重复。它由HashMap* 内部支持,它基于散列原理工作。我们可以在HashSet中存储一个 值。其默认容量为16,负载系数为0.75,HashSet是非同步的也就是说是非线程安全的。此外,无法保证保留元素的插入顺序。 2.2、TreeSet的本质是一个"有序的,并且没有重复元素"的集合,

2.3、LinkedHashSet是Set集合的一个实现,具有set集合不重复的特点,同时具有可预测的迭代顺序,也就是我们插入的顺序。跟进LinkedHashSet可以得到super一个父类初始化为一个容器为16大小,加载因子为0.75的Map容器。

3、Map与List、Set接口不同,它是由一系列键值对组成的集合,提供了key到Value的映射。在Map中它保证了key与value之间的一一对应关系。也就是说一个key对应一个value,所以它不能存在相同的key值,当然value值可以相同。实现map的集合有:HashMap、HashTable、TreeMap、WeakHashMap。

3.1、HashMap 数据节点Entry节点 插入数据方法是头插法,扩容机制、默认容量16 因子0.75 会扩大两倍

1、jdk1.7、HashMap由数组和链表来实现对数据的存储、们可以发现数据结构由数组+链表组成,一个长度为16的数组中,每个元素存储的是一个链表的头结点。那么这些元素是按照什么样的规则存储到数组中呢。一般情况是通过hash(key.hashCode())%len获得,也就是元素的key的哈希值对数组长度取模得到。比如上述哈希表中,12%16=12,28%16=12,108%16=12,140%16=12。所以12、28、108以及140都存储在数组下标为12的位置。

2、JDK8之后, 数据Nod节点 HashMap的实现方式做了一些改变,但是基本思想还是没有变得,只是在一些地方做了优化,下面来看一下这些改变的地方,数据结构的存储由数组+链表的方式,变化为数组+链表+红黑树的存储方式,当链表长度超过阈值(8)时,将链表转换为红黑树。在性能上进一步得到提升。如果哈希表单向链表中元素超过8个,那么单向链表这种数据结构会变成红黑树数据结构。当红黑树上的节点数量小于6个,会重新把红黑树变成单向链表数据结构。

节点个数是多少的时候,链表会转变成红黑树。链表节点个数大于等于 8 时,链表会转换成树结构。节点个数是多少的时候,红黑树会退回链表。节点个数小于等于 6 时,树会转变成链表。为什么转变条件 8 和 6 有一个差值。如果没有差值,都是 8 ,那么如果频繁的插入删除元素,链表个数又刚好在 8 徘徊,那么就会频繁的发生链表转树,树转链表。

HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75

3.2、hashTable

1、HashTable是较为远古的使用Hash算法的容器结构了,现在基本已被淘汰,单线程转为使用HashMap,多线程使用ConcurrentHashMap。HashTable的操作几乎和HashMap一致,主要的区别在于HashTable为了实现多线程安全,在几乎所有的方法上都加上了synchronized锁,而加锁的结果就是HashTable操作的效率十分低下。

3.3 TreeMap

1、在Map集合框架中,除了HashMap以外,TreeMap也是常用到的集合对象之一。与HashMap相比,TreeMap是一个能比较元素大小的Map集合,会对传入的key进行了大小排序。其中,可以使用元素的自然顺序,也可以使用集合中自定义的比较器来进行排序;不同于HashMap的哈希映射,TreeMap实现了红黑树的结构,形成了一颗二叉树。

总结:

1、List、Set都是继承自Collection接口,Map则不是

2、List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。)

3、Set和List对比:

Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。

List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。

4、Map适合储存键值对的数据

5、线程安全集合类与非线程安全集合类 :

  • LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;

  • HashMap是非线程安全的,HashTable是线程安全的;

  • StringBuilder是非线程安全的,StringBuffer是线程安全的。

3.2、java.util.concurrent包

1、ConcurrentHashMap 、数组+链表+红黑树的存储方式,它自会锁住获取到的那个Entry节点 上锁的 cas+sysnchronized

jdk1.6后对 sysnchronized 升级后,concurrenHashMap集合

JDK8中ConcurrentHashMap参考了JDK8 HashMap的实现,采用了数组+链表+红黑树的实现方式来设计,内部大量采用CAS操作。并发控制使⽤synchronized 和 CAS 来操作。(JDK1.6 以后 对 synchronized 锁做了很多优化) 整个看起来就像是优化过且线程安全的 HashMap,虽然在 JDK1.8 中还能看到 Segment 的数据结构,但是已经简化了属性,只是为了兼容旧版本;JDK1.8的Nod节点中value和next都用volatile修饰,保证并发的可见性。

2、CopyOnWriteArrayList这是一个ArrayList的线程安全的变体,其原理大概可以通俗的理解为:初始化的时候只有一个容器,很长一段时间,这个容器数据、数量等没有发生变化的时候,大家(多个线程),都是读取(假设这段时间里只发生读取的操作)同一个容器中的数据,所以这样大家读到的数据都是唯一、一致、安全的,但是后来有人往里面增加了一个数据,这个时候CopyOnWriteArrayList 底层实现添加的原理是先copy出一个容器(可以简称副本),再往新的容器里添加这个新的数据,最后把新的容器的引用地址赋值给了之前那个旧的的容器地址,但是在添加这个数据的期间,其他线程如果要去读取数据,仍然是读取到旧的容器里的数据。

3、CopyOnWriteArraySet它是线程安全的无序的集合,可以将它理解成线程安全的HashSet,有意思的是,CopyOnWriteArraySet和HashSet虽然都继承于共同的父类都继承于共同的父类;但是,HashSet是通过“散列表(HashMap)”实现的,而CopyOnWriteArraySet则是通过“动态数组(CopyOnWriteArrayList)”实现的,并不是散列表。和CopyOnWriteArrayList类似

3.3、 java容器有那些,那些事同步容器,那些事并发容器

1.1、同步容器、Vector、Stack、HashTable、Collections.synchronized方法生成

1.2、并发容器、ConcurrentHashMap:线程安全的HashMap的实现、CopyOnWriteArrayList:线程安全且在读操作时无锁的ArrayList、CopyOnWriteArraySet:基于CopyOnWriteArrayList,不添加重复元素、ArrayBlockingQueue:基于数组、先进先出、线程安全,可实现指定时间的阻塞读写,并且容量可以限制、LinkedBlockingQueue:基于链表实现,读写各用一把锁,在高并发读写操作都多的情况下,性能优于ArrayBlockingQueue

4、Spring

4.1、Spring注解

@Controller 组合注解(组合了@Component注解),应用在MVC层(控制层),DispatcherServlet会自动扫描注解了此注解的类,然后将web请求映射到注解了@RequestMapping的方法上。

@RequestMapping 是一个用来处理请求地址映射的注解

@Resource默认按照byName方式进行bean匹配

@Autowired @Autowired顾名思义,就是自动装配

@ModelAttribute和 @SessionAttributes

@PathVariable

@requestParam

@ResponseBody

@Component

@Configuration

4.2、java反射原理、注解原理?

反射机制、java运行状态中、对于任意类对象都能知道这个类对象的所有属性跟发法,

这种动态获取信息的功能称为反射机制,

程序可以访问、检测和修改它本身状态或行为的能力,即自描述和自控制,可以在运行时加载、探知和使用编译期间完全未知的类。Reflection

Java在编译之后会生成一个class文件,反射通过字节码文件找到其类中的方法和属性

注解:

注解是一种特殊的元数据,元数据是关于数据的数据,所以,注解就是代码的元数据。我们用@Override注解toString()方法,说明我们要重写toString()方法。这里,即使我们不用@Override注解,这个方法任然可以正常执行。那注解的好处是什么呢?@Override告诉编译器,子类要重写这个方法,需要按照自己定义的格式输出内容,也就是覆盖了父类的方法,如果父类中没有这个方法,编译器就会报错。

4.3、请详细描述SpringMVC处理请求全流程

首先,用户的浏览器发出了一个请求,这个请求经过互联网到达了我们的服务器。

Servlet 容器首先接待了这个请求,并将该请求委托给 DispatcherServlet 进行处理。

接着 DispatcherServlet 将该请求传给了处理器映射组件 HandlerMapping,并获取到适合该请求的拦截器和处理器。

在获取到处理器后,DispatcherServlet 还不能直接调用处理器的逻辑,需要进行对处理器进行适配。

处理器适配成功后,DispatcherServlet 通过处理器适配器 HandlerAdapter 调用处理器的逻辑,并获取返回值 ModelAndView。

之后,DispatcherServlet 需要根据 ModelAndView 解析视图。解析视图的工作由 ViewResolver 完成,若能解析成功,ViewResolver 会返回相应的视图对象 View。

在获取到具体的 View 对象后,最后一步要做的事情就是由 View 渲染视图,并将渲染结果返回给用户。

4.4、Spring主要使用了什么模式?

· 工厂模式:每个Bean的创建通过方法

· 单例模式:默认的每个Bean的作用域都是单例

· 代理模式:关于Aop的实现通过代理模式

4.5、Spring Aop 切面

 * AOP{动态代理}
 *   指在程序运行期间动态的将某段代码切入到指定位置进行运行的编程
 *
 * 1、导入aop模块,Spring AOP(spring-aspects)
 * 2、定义一个业务逻辑类,(MathCalculator)在业务逻辑运行的时候将日志进行打印。(方法之前、方法结束、方法异常等)
 * 3、定义一个日志切面类LogAspects 、切面类里面的方法、需要动态感知MathCalculator.div运行到哪里后
 *       通知方法:
 *               前置通知:(@Before)logStart 在目标方法div运行之前
 *               后置通知 (@After)logEnd 在目标方法div运行之后
 *               返回通知:(@AfterReturning)logReturn 在目标方法(div)正常返回之后运行
 *               异常通知:(@AfterThrowing) logException 在目标方法div运行异常后运行
 *               环绕通知:(@Around)动态代理、手动推动目标方法运行
 * 4、给切面类的目标方法标注何时运行(标注注解)都加入到容器中
 * 5、将切面类和业务逻辑类(目标方法所在的类)
 * 6、必须告诉spring 哪个类是切面类(给切面类加一个注解){@Aspect}
 * 7、给配置类加@EnableAspectJAutoProxy(开启基于注解的AOP模式)
 *
 * 三步
 *
 *   1、将业务逻辑组件和却面类都加入到容器中,告诉Spring哪个是切面类(@Aspect)
 *   2、在切面类上的每一个通知方法上标注通知注解、告诉Spring何时何地运行(切入点表达式)
 *   3、开启基于注解的aop模式,@EnableAspectJAutioProxy

4.6、SpringIOC 的理解,原理与实现

控制反转:理论思想,原来的对象是由使用者进行控制、有了spring之后,可以把整个对象交给spring来帮我们进行管理,

依赖注入、把对应的属性的值注入到集体对象中,@Autowired,populateBean完成属性注入。

容器、存储对象,使用map结构来存储,在spring中一般存在三级缓存,singletonObjects存放完整的bean对象,整个bean的生命周期,从创建到使用到销毁的过程全部都由容器来管理。

5、SpringBoot

5.1、springboot中application 的运行机制

配置文件定义属性、自动装配到所属依赖的一个类里面,再以他的这种动态代理方式、进入到spring容器中去

springboot通过根据配置文件、自动装配所属依赖的类、再用动态代理的方式、注入到spring容器里面。

springbootapplication 进入后有三个注解、configuration、enableAutoConfiguration、ComponentScan

configuration、它是用来标注一个类为配置类。

componentScan、他是用来将指定的包下面、需要装配的组件、注册到容器里面去。

enableAutoConfiguration、他是核心注解、进入它里面会发现包含两个注解 AutoConfigurationPackage\import,

AutoConfigurationPackage将主配置类所在的包、作为自动装配的包进行管理

import是倒入一个类到IOC容器中、根据meta-info下面的、spring.factories的配置进行导

5.2、component和bean的区别

@Component注解表明一个类会作为组件类,并告知Spring要为这个类创建bean。

@Bean注解告诉Spring这个方法将会返回一个对象,这个对象要注册为Spring应用上下文中的bean。通常方法体中包含了最终产生bean实例的逻辑。

相同点:两者的结果都是为spring容器注册Bean.

不同点:@Component 通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中。

@Bean 注解通常是我们在标有该注解的方法中定义产生这个bean的逻辑。

5.3、什么是 Spring Boot?

Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。

5.4、Spring Boot有哪些优点?

-快速创建独立运行的spring项目与主流框架集成

-使用嵌入式的servlet容器,应用无需打包成war包 -starters自动依赖与版本控制 -大量的自动配置,简化开发,也可修改默认值 -准生产环境的运行应用监控 -与云计算的天然集成

5.5、Spring Boot 的配置文件有哪几种格式?

*.properties 和 *.yml,它们的区别主要是书写格式不同。.yml是一种人类可读的数据序列化语言。properties 是属性配置文件;与属性文件相比,如果我们想要在配置文件中添加复杂的属性,yml文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。.yml 格式不支持 @PropertySource 注解导入配置

5.6、Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?

启动类注解是@SpringBootApplication,它也是 Spring Boot 的核心注解 主要组合包含了以下 3 个注解: 1,@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。 2,@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。 3,@ComponentScan:Spring组件扫描。

5.7、SpringBoot 实现热部署有哪几种方式

主要有两种方式:

· Spring Loaded

· Spring-boot-devtools

6、mybatis

6.1、mybatis的二级缓存

他的一级缓存能加快查询速率、比如第一次查询跟第二次查询数据没有变、mybatis会重一级缓存中获取数据、这边就提示速率同时减轻数据库的压力。

二级缓存、在mybatis的配置文件中开启二级缓存、并且在mapper.xml中打上cache标签就可以

mybatis嵌套查询跟嵌套结果有什么区别

mybatis #和dollar符号区别

6.2、Mybatis在核心处理类叫什么?

SqlSession

6.3、查询表名和返回实体Bean对象不一致,如何处理?

映射键值对即可

 <result column="title" property="title" javaType="java.lang.String"/>

· column:数据库中表的列名

· property:实体Bean中的属性名

6.4、${} 和 #{}的区别?

· ${}:简单字符串替换,把${}直接替换成变量的值,不做任何转换,这种是取值以后再去编译SQL语句。

· #{}:预编译处理,sql中的#{}替换成?,补全预编译语句,有效的防止Sql语句注入,这种取值是编译好SQL语句再取值。 总结:一般用#{}来进行列的代替

6.5、Mybatis配置一对多?

 <collection property="topicComment" column="id" ofType="com.tmf.bbs.pojo.Comment" select="selectComment" />

· property:属性名

· column:共同列

· ofType:集合中元素的类型

select:要连接的查询

6.6、Mybatis配置一对一?

 <association property="topicType" select="selectType" column="topics_type_id" javaType="com.tmf.bbs.pojo.Type"/>

· property:属性名

· select:要连接的查询

· column:共同列

· javaType:集合中元素的类型

6.4、Mybatis的好处?

· 把Sql语句从Java中独立出来。

· 封装了底层的JDBC,API的调用,并且能够将结果集自动转换成JavaBean对象,简化了Java数据库编程的重复工作。

· 自己编写Sql语句,更加的灵活。

· 入参无需用对象封装(或者map封装),使用@Param注解

7、mysql

7.1、mysql的索引,底层数据结构是什么

B+树 B+tree

1、唯一索引和普通索引 普通索引:是MySQL中的基本索引类型,允许在定义索引的列中插入重复值和空值。 唯一索引:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。 主键索引:是一种特殊的唯一索引,不允许有空值。

2、单列索引和组合索引 单列索引:即一个索引只包含单个列,一个表可以有多个单列索引; 组合索引:指在表的多个字段组合上创建的索引。只有在查询条件中使用了这些字段的左边字段时,索引才会被使用。使用组合索引时遵循最左前缀集合。

3、全文索引( fulltext) 全文索引类型为FULLTEXT,在定义索引的列上支持值得全文查找,允许在这些索引列 中插入重复值和空值。全文索引可以在CHAR、VARCHAR或者TEXT类型的列上创建。MySQL 5.7.xx之前只有MyISAM存储引擎支持全文索引。

4、空间索引 空间索引是对空间数据类型的字段建立的索引,MySQL中的空间数据类型有4中,分别是: geometry、point、linstring和polygon 。MySQL使用SPATIAL关键字进行扩展,使得能够用于创建空间索引的列,必须将其声明为NOT NULL,同样,在MySQL 5.7.xx之前,空间索引只能在存储引擎为MyISAM的表中创建。 5、创建索引的规则

  • 创建索引并非是越多越好,一个表中如果有大量的索引,不仅占用磁盘空间,而且会影响

  • insert、delete、update等语句的性能。因为当表中的数据更改时,索引也会进行调整和更新;

  • 数据量小得表最好不要创建索引,由于数据较少,查询花费的时间可能比遍历索引的时间还要长;

  • 避免对经常更新的数据创建索引。而对经常用于查询的字段应该创建索引;

  • 在条件表达式中经常用到的不同值较多的列创建索引;

  • 当唯一性是某种数据本身的特征时,我们创建唯一性索引;

  • 在频繁进行排序或分组的列上建立索引,如果排序的列有多个,可以创建组合索引;

7.2、sql优化

  1. explain出来的各种item的意义;

  2. profile的意义以及使用场景;

    1)、id列数字越大越先执行,如果说数字一样大,那么就从上往下依次执行,id列为null的就表是这是一个结果集,不需要使用它来进行查询。 2)、select_type列常见的有: A:simple:表示不需要union操作或者不包含子查询的简单select查询。有连接查询时,外层的查询为simple,且只有一个 B:primary:一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type即为primary。且只有一个 C:union:union连接的两个select查询,第一个查询是dervied派生表,除了第一个表外,第二个以后的表select_type都是union D:dependent union:与union一样,出现在union 或union all语句中,但是这个查询要受到外部查询的影响 E:union result:包含union的结果集,在union和union all语句中,因为它不需要参与查询,所以id字段为null F:subquery:除了from字句中包含的子查询外,其他地方出现的子查询都可能是subquery G:dependent subquery:与dependent union类似,表示这个subquery的查询要受到外部表查询的影响 H:derived:from字句中出现的子查询,也叫做派生表,其他数据库中可能叫做内联视图或嵌套select 3)、table 显示的查询表名,如果查询使用了别名,那么这里显示的是别名,如果不涉及对数据表的操作,那么这显示为null,如果显示为尖括号括起来的<derived N>就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生。如果是尖括号括起来的<union M,N>,与<derived N>类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集。 4)、type 依次从好到差:system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,index_subquery,range,index_merge,index,ALL,除了all之外,其他的type都可以使用到索引,除了index_merge之外,其他的type只可以用到一个索引 A:system:表中只有一行数据或者是空表,且只能用于myisam和memory表。如果是Innodb引擎表,type列在这个情况通常都是all或者index B:const:使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。其他数据库也叫做唯一索引扫描 C:eq_ref:出现在要连接过个表的查询计划中,驱动表只返回一行数据,且这行数据是第二个表的主键或者唯一索引,且必须为not null,唯一索引和主键是多列时,只有所有的列都用作比较时才会出现eq_ref D:ref:不像eq_ref那样要求连接顺序,也没有主键和唯一索引的要求,只要使用相等条件检索时就可能出现,常见与辅助索引的等值查找。或者多列主键、唯一索引中,使用第一个列之外的列作为等值查找也会出现,总之,返回数据不唯一的等值查找就可能出现。 E:fulltext:全文索引检索,要注意,全文索引的优先级很高,若全文索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引 F:ref_or_null:与ref方法类似,只是增加了null值的比较。实际用的不多。 G:unique_subquery:用于where中的in形式子查询,子查询返回不重复值唯一值 H:index_subquery:用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重。 I:range:索引范围扫描,常见于使用>,<,is null,between ,in ,like等运算符的查询中。 J:index_merge:表示查询使用了两个以上的索引,最后取交集或者并集,常见and ,or的条件使用了不同的索引,官方排序这个在ref_or_null之后,但是实际上由于要读取所个索引,性能可能大部分时间都不如range K:index:索引全表扫描,把索引从头到尾扫一遍,常见于使用索引列就可以处理不需要读取数据文件的查询、可以使用索引排序或者分组的查询。 L:all:这个就是全表扫描数据文件,然后再在server层进行过滤返回符合要求的记录。 5)、possible_keys 查询可能使用到的索引都会在这里列出来 6)、key 查询真正使用到的索引,select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。 7)、key_len 用于处理查询的索引长度,如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查询不一定都能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去,没有使用到的列,这里不会计算进去。留意下这个列的值,算一下你的多列索引总长度就知道有没有使用到所有的列了。要注意,mysql的ICP特性使用到的索引不会计入其中。另外,key_len只计算where条件用到的索引长度,而排序和分组就算用到了索引,也不会计算到key_len中。 8)、ref 如果是使用的常数等值查询,这里会显示const,如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段,如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func 9)、rows 这里是执行计划中估算的扫描行数,不是精确值 10)、extra 这个列可以显示的信息非常多,有几十种,常用的有 A:distinct:在select部分使用了distinc关键字 B:no tables used:不带from字句的查询或者From dual查询 C:使用not in()形式子查询或not exists运算符的连接查询,这种叫做反连接。即,一般连接查询是先查询内表,再查询外表,反连接就是先查询外表,再查询内表。 D:using filesort:排序时无法使用到索引时,就会出现这个。常见于order by和group by语句中 E:using index:查询时不需要回表查询,直接通过索引就可以获取查询的数据。 F:using join buffer(block nested loop),using join buffer(batched key accss):5.6.x之后的版本优化关联查询的BNL,BKA特性。主要是减少内表的循环数量以及比较顺序地扫描查询。 G:using sort_union,using_union,using intersect,using sort_intersection: using intersect:表示使用and的各个索引的条件时,该信息表示是从处理结果获取交集 using union:表示使用or连接各个使用索引的条件时,该信息表示从处理结果获取并集 using sort_union和using sort_intersection:与前面两个对应的类似,只是他们是出现在用and和or查询信息量大时,先查询主键,然后进行排序合并后,才能读取记录并返回。 H:using temporary:表示使用了临时表存储中间结果。临时表可以是内存临时表和磁盘临时表,执行计划中看不出来,需要查看status变量,used_tmp_table,used_tmp_disk_table才能看出来。 I:using where:表示存储引擎返回的记录并不是所有的都满足查询条件,需要在server层进行过滤。查询条件中分为限制条件和检查条件,5.6之前,存储引擎只能根据限制条件扫描数据并返回,然后server层根据检查条件进行过滤再返回真正符合查询的数据。5.6.x之后支持ICP特性,可以把检查条件也下推到存储引擎层,不符合检查条件和限制条件的数据,直接不读取,这样就大大减少了存储引擎扫描的记录数量。extra列显示using index condition J:firstmatch(tb_name):5.6.x开始引入的优化子查询的新特性之一,常见于where字句含有in()类型的子查询。如果内表的数据量比较大,就可能出现这个 K:loosescan(m..n):5.6.x之后引入的优化子查询的新特性之一,在in()类型的子查询中,子查询返回的可能有重复记录时,就可能出现这个

7.3、mysql 建立索引的原则

1.选择唯一性索引

唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。例如,学生表中学号是具有唯一性的字段。为该字段建立唯一性索引可以很快的确定某个学生的信息。如果使用姓名的话,可能存在同名现象,从而降低查询速度。 2.为经常需要排序、分组和联合操作的字段建立索引 经常需要ORDER BY、GROUP BY、DISTINCT和UNION等操作的字段,排序操作会浪费很多时间。如果为其建立索引,可以有效地避免排序操作。 3.为常作为查询条件的字段建立索引 如果某个字段经常用来做查询条件,那么该字段的查询速度会影响整个表的查询速度。因此,为这样的字段建立索引,可以提高整个表的查询速度。 4.限制索引的数目 索引的数目不是越多越好。每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大。修改表时,对索引的重构和更新很麻烦。越多的索引,会使更新表变得很浪费时间。 5.尽量使用数据量少的索引 如果索引的值很长,那么查询的速度会受到影响。例如,对一个CHAR(100)类型的字段进行全文检索需要的时间肯定要比对CHAR(10)类型的字段需要的时间要多。 6.尽量使用前缀来索引 如果索引字段的值很长,最好使用值的前缀来索引。例如,TEXT和BLOG类型的字段,进行全文检索会很浪费时间。如果只检索字段的前面的若干个字符,这样可以提高检索速度。 7.删除不再使用或者很少使用的索引 表中的数据被大量更新,或者数据的使用方式被改变后,原有的一些索引可能不再需要。数据库管理员应当定期找出这些索引,将它们删除,从而减少索引对更新操作的影响。 8 . 最左前缀匹配原则,非常重要的原则。 mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a 1=”” and=”” b=”2” c=”“> 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。 9 .=和in可以乱序。 比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式 10 . 尽量选择区分度高的列作为索引。 区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就 是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是0.1以上,即平均1条扫描10条 记录 11 .索引列不能参与计算,保持列“干净”。 比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本 太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’); 12 .尽量的扩展索引,不要新建索引。 比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可 13、当单个索引字段查询数据很多,区分度都不是很大时,则需要考虑建立联合索引来提高查询效率

7.4、慢查询日志

MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中。long_query_time的默认值为10,意思是运行10S以上的语句。默认情况下,MySQLl数据库并不启动慢查询日志,需要我们手动来设置这个参数,当然,如果不是调优需要的话,一般不建议启动该参数,因为开启慢查询日志会或多或少带来一定的性能影响。慢查询日志支持将日志记录写入文件,也支持将日志记录写入数据库表。

1. 查看慢日志参数:

 --查询配置命令show variables like '%query%';--当前配置参数binlog_rows_query_log_events    OFFft_query_expansion_limit    20have_query_cache    YES--时间限制,超过此时间,则记录long_query_time    10.000000query_alloc_block_size    8192query_cache_limit    1048576query_cache_min_res_unit    4096query_cache_size    1048576query_cache_type    OFFquery_cache_wlock_invalidate    OFFquery_prealloc_size    8192--是否开启慢日志记录slow_query_log    OFF--日志文件slow_query_log_file    D:\Program Files (x86)\mysql-5.7.18-winx64\data\Jack-slow.log--

2. 修改当前配置

 set global 变量名 = 值;--例如,修改时间限制为20slong_query_time = 20;

ps.也可以直接打开慢日志配置文件进行修改,但必须重启服务才能生效

7.3、 查看MySQL慢日志

mysqldumpslow -s at -a  /usr/local/var/mysql/MacBook-Pro-3-slow.log --verbose    版本--debug      调试--help       帮助 -v           版本-d           调试模式-s ORDER     排序方式             what to sort by (al, at, ar, c, l, r, t), 'at' is default              al: average lock time              ar: average rows sent              at: average query time               c: count               l: lock time               r: rows sent               t: query time-r           反转顺序,默认文件倒序拍。reverse the sort order (largest last instead of first)-t NUM       显示前N条just show the top n queries-a           不要将SQL中数字转换成N,字符串转换成S。don't abstract all numbers to N and strings to 'S'-n NUM       abstract numbers with at least n digits within names-g PATTERN   正则匹配;grep: only consider stmts that include this string-h HOSTNAME  mysql机器名或者IP;hostname of db server for *-slow.log filename (can be wildcard),             default is '*', i.e. match all-i NAME      name of server instance (if using mysql.server startup script)-l           总时间中不减去锁定时间;don't subtract lock time from total time

7.4、mysql中索引类型

1、普通索引、允许被索引的数据列包含重复的值

2、唯一索引、可以保证数据记录的唯一性

3、主键、是一种特殊的唯一索引、在一张表中只能定义一个主键索引,主键用于唯一标识一条记录,使用关键字PRIMARY KEY来创建,

4、联合索引、索引可以覆盖多个数据列,如像INDEX(columnA,columnB)索引

5、全文索引、通过建立倒排索引、可以极大的提升检索效率,解决判断字段是否包含的问题,是目前搜索引擎使用的一种关键技术、可以通过ALTER TABLE table_name ADD FULLTEXT (column)创建全文索引。

7.5、mysql聚簇和非聚簇索引的区别

都是B+树的数据结构

聚簇索引、将数据存储与索引放到了一块、并且是按照一定的顺序组织的,找到索引也就找到了数据,数据的物理存放顺序与索引顺序是一致的,即只要索引是相邻的、那么对应的数据一定也是相邻地存放在磁盘上的,

非聚簇索引、叶子节点不存放数据,存储的是数据行地址,也就是说根据索引查找找到数据行的位置再取磁盘查找数据,这个就有点类似一本书的目录,比如我们要找第三章第一节,那我们先在这个目录里面找到,找到对应的页码后再去对应的页码看文章。

7.6、什么是事务隔离

多个事务之间隔离的,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题。 存在问题: 1. 脏读:一个事务,读取到另一个事务中没有提交的数据 2. 不可重复读(虚读):在同一个事务中,两次读取到的数据不一样。 3. 幻读:一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。 隔离级别: 1. read uncommitted:读未提交 产生的问题:脏读、不可重复读、幻读 2. read committed:读已提交 (Oracle默认) 产生的问题:不可重复读、幻读 3. repeatable read:可重复读 (MySQL默认) 产生的问题:幻读 4. serializable:串行化 可以解决所有的问题

7.7、proxy和jdbc优缺点?

jdbc支持跨数据库但是不支持跨语言 proxy支持跨语言但是不支持跨数据库

8、redis

8.1、redis持久化

一、RDB

1、在指定的时间间隔内将内存中的数据集快照写入磁盘中。

2、优点、节省磁盘空间、恢复速度快。

3、缺点、在数据较大的情况还是会损耗性能,redis意外down掉的话,就会丢失最后一次快照后的所有修改。

二、AOF

1、已日志的形式记录下来,将所有写的操作都记录到文件中,只追加不修改文件。

2、优点、备份机制更稳定,丢失数据几率低。可读的日志文件、通过操作AOF文件可以处理误操作数据。

3、缺点、比起RDB占用更多的磁盘空间、恢复备份速度要慢、每次读写都要同步的话,有一定的性能压力,存在个别Bug,会造成数据不能恢复。

8.2、redis 中的数据类型。

1、String、

2、Hash

3、List

4、Set

5、Zset

8.3、redis中缓存雪崩、缓存击穿是什么、如何处理

缓存雪崩是、redis中的key大面积的失效、导致直接请求数据库信息,这时候会给数据库压力、同时在高并发下可能会使数据库崩溃

解决效果是、可以将设置一个不同的过期时间、比如叫一个random随机数、同时如果某些key经常被使用又很少修改缓存信息则可以将该key设置为热点key、不设置过期时间

缓存击穿是、某个key在缓存与数据库中同时查不到数据、这时候一直获取该缓存信息导致数据库崩溃。

解决、可以在该key数据库查询不到的时候设置值为null,同时设置一个过期时间或者在数据库有值的同时将key设为该值。

8.4、redis 淘汰策略

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

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

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

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

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

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

8.5、redis的过期键的删除策略

redis是key-value数据库,我们可以设置Redis中缓存的key的过期时间,redis的过期策略就是指当redis中缓存的key过期了,redis如何处理

惰性过期、只有当访问一个key时,才会判断该key是否已经过期,过期则清楚,该策略可以最大化地节省CPU资源,却对内存非常不友好,极端情况可能出现大量过期key没有再次访问,从而不会被清楚,占用大量内存。

定时过期、

定期过期、每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中过期的key,该策略时最两者的一个折中方案,通过调整定时扫描时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。

8.6、redis 单线程 为什么这么快

io复用、基于内存的

8.7、redis 有哪些适合的场景

1、分布式session 2、接口幂等性、唯一性 3、缓存 4、排行榜 5、队列、订阅

8.9、为什么要用消息中间件Rocketmq

解耦、异步、消峰、分布式应用程序需要垂直拆分、依赖调用增多

9、linux

9.1、linux常见 命令

tail -f

traceroute ip 查看路由

top -p pid

kill -9

ps -ef|grep java

9.2、linux查看系统负载情况

uptime、w、top

10、springCloud

10.1、简单的说一下你对分布式的理解

分布式服务是比如,微服务将同一个系统中将不同的业务拆分成一个单独的服务,可以将这些服务交给其他团队去开发运维。

10.2、springcloud有哪些组件

Eureka服务就是很多的服务、所以需要有一个注册中心进行服务注册管理,就是将所有的服务注册到注册中心里面去,其它服务需要调用也需要从注册中心里面去获取。

Ribbon或者feign它是做负载均衡调用的,它从注册中心拿到一堆服务列表,比如有3个这时候就需要通过负载均衡去调用它,比如轮询、权重、随机、hash等机制进行负载分配。

Hystrix比如当我们调用服务的时候、服务突然挂了,为了服务健壮性,我们就需要用到Hystrix,它主要就是用到熔断和降级以及限流的

config、我们众多服务的话需要一个配置,如果我们把配置放到不同的服务当中,那么管理起来比较麻烦,所以就有了一个统一的配置中心。

Zuul、就是我们有很多个服务、这些服务都是给前端调用的,如果是一个服务就有一个地址。它也是不好管理的。为了统一地址和鉴权、限流等操作,就用到了网关。

10.3、作为服务注册中心,Eureka比Zookeeper好在哪里?

著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)和P(分区容错性)。由于分区容错性P在是分布式系统中必须要保证的,因此我们只能在A和C之间进行权衡。

因此,Zookeeper 保证的是CP, Eureka 则是AP。

10.4、什么是服务熔断?什么是服务降级?

服务直接的调用,比如在高并发情况下出现进程阻塞,导致当前线程不可用,慢慢的全部线程阻塞,导致服务器雪崩。

服务熔断:相当于保险丝,出现某个异常,直接熔断整个服务,而不是一直等到服务超时。通过维护一个自己的线程池,当线程到达阈值的时候就启动服务降级,如果其他请求继续访问就直接返回fallback的默认值。

服务降级是在服务器压力陡增的情况下,利用有限资源,根据当前业务情况,关闭某些服务接口或者页面,以此释放服务器资源以保证核心任务的正常运行。

10.5、介绍一下目前微服务框架如何选型

1、注册中心 Eureka (停更)Zookeeper\Consul\Nacos.(8848)

2、服务调用 Ribbon\LoadBalancer

3、服务调用2 Feign(停更)\OpenFeign

4、服务降级 Hysrix(停更)\resilience4j\sentienl(8401)

5、服务网关 Zuul(停更) \Zuul2(待定)\gateway(网关)

gateway 使用的webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架

6、服务配置、Config(停更)|Nacos

7、服务总线、Bus(停更)|Nacos

8、数据库分布式事务、Seata

组件名 语言 CAP 服务健康检查 对外暴露接口 SpringCloud集成

Eureka Java AP 可配支持 HTTP 已集成 Consul Go CP 支持 HTTP/DNS 已集成 Zookeeper java CP 支持 客户端 已集成 Nacos java AP|CP 支持切换 三个注册中心异同店 CAP C:Consistency(强一致性) A:Availability(可用性) P:Partition tolerance(分区容错性) CAP理论关注力度是数据,而不是整体系统设计的策略

最多只能同时较好的满足两个 CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求, 因此,根据CAP原来将NoSQL数据库分成了满足CA原子,满足CP原则和满足AP原则三大类: CA-单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大 CP-满足一致性,分区容忍必的系统,通常性能不是特别高。 AP-满足可用性,分区容忍性的系统,通常可能对一致性要求低一些

10.6、分布式事务

下订单、减库存、扣余额、改状态。

seata GlobalTransactional

11、多线程

11.1、创建线程的三种方法

继承 extends Thread、实现 implements Runnable、实现 implements Callable

FutureTask<String> futureTask=new FutureTask<String>(callable);

11.2、线程池ThreadPoolExecutor七大参数

1、corePoolSize 线程池中常驻核心线程数

2、maximumPoolSize 线程池能够容纳同时执行的最大线程数,值必须大于0

3、keepAliveTime多余的空闲线程的存活时间

4、unit 过期时间单位

5、workQueue任务队列,被提交但尚未被执行的任务

6、threadFactory表示生成线程池中的工作线程的线程工厂,一般用默认的

7、handler拒绝策略,表示当队列满了并且工作线程大于等于线程池的最大线程数。则采取拒绝策略

AbortPolicy(默认) 丢弃任务并抛出RejectedExecutionException异常 CallerRunsPolicy 由调用线程处理该任务

DiscardOldestPolicy丢弃队列最前面的任务,然后重新提交被拒绝的任务。

DiscardPolicy丢弃任务,但是不抛出异常。如果线程队列已满,则后续提交的任务都会被丢弃,且是静默丢弃。

ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务

11.3、线程的生命周期

它要经过新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)5种状态

\1. 新建状态,当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时仅由JVM为其分配内存,并初始化其成员变量的值

\2. 就绪状态,当线程对象调用了start()方法之后,该线程处于就绪状态。Java虚拟机会为其创建方法调用栈和程序计数器,等待调度运行

\3. 运行状态,如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态

\4. 阻塞状态,当处于运行状态的线程失去所占用资源之后,便进入阻塞状态

\5. 在线程的生命周期当中,线程的各种状态的转换过程

11.4、wait 和sleep 区别

sleep来自Thread类,和wait来自Object类。

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

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

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

yieId()执行后线程直接进入就绪状态,马上释放了CPU的执行权,但是依然保留CPU的执行资格所以有可能cpu下次进行线程调度的时候还会让这个线程获取到执行权继续执行 join() 执行后线程进入阻塞状态,例如在线程B中调用线程A的join(),那么线程B会进入阻塞队列,直到线程A结束或中断线程

11.5、如果你提交任务时、线程池队列已满,这时会发生什么

1、如果使用的无界队列、那么可以继续提交任务时没关系 2、如果使用的有界队列、提交任务时,如果队列满了,如果核心线程书没有达到上限,那么则增加线程,如果线程数已经达到了最大值,则使用拒绝策略进行拒绝。

11.6、查看死锁

多个线程持有互相资源,并且等待对方资源进行释放的前提下,排查Jstack pid

12、垃圾回收器

12.1、简述Java垃圾回收机制

在java中,程序员是不需要显示的去释放一个对象的内存的,而是由虚拟机自行执行。在JVM中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫面那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。

12.2、GC是什么?为什么要GC

GC 是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存

回收会导致程序或系统的不稳定甚至崩溃,Java 提供的 GC 功能可以自动监测对象是否超过作用域从而达到自动

回收内存的目的,Java 语言没有提供释放已分配内存的显示操作方法。

12.3、Java 中都有哪些引用类型?

  • 强引用:发生 gc 的时候不会被回收。

  • 软引用:有用但不是必须的对象,在发生内存溢出之前会被回收。

  • 弱引用:有用但不是必须的对象,在下一次GC时会被回收。

  • 虚引用(幽灵引用/幻影引用):无法通过虚引用获得对象,用 PhantomReference 实现虚引用,虚引用的用途是在 gc 时返回一个通知。

12.4、怎么判断对象是否可以被回收?

垃圾收集器在做垃圾回收的时候,首先需要判定的就是哪些内存是需要被回收的,哪些对象是「存活」的,是不可以被回收的;哪些对象已经「死掉」了,需要被回收。

一般有两种方法来判断:

  • 引用计数器法:为每个对象创建一个引用计数,有对象引用时计数器 +1,引用被释放时计数 -1,当计数器为 0 时就可以被回收。它有一个缺点不能解决循环引用的问题;

  • 可达性分析算法:从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是可以被回收的。

12.5、在Java中,对象什么时候可以被垃圾回收

当对象对当前使用这个对象的应用程序变得不可触及的时候,这个对象就可以被回收了。

垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC)。如果你仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的。这就是为什么正确的永久代大小对避免Full GC是非常重要的原因。

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

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

  • 复制算法:按照容量划分二个大小相等的内存区域,当一块用完的时候将活着的对象复制到另一块上,然后再把已使用的内存空间一次清理掉。缺点:内存使用率不高,只有原来的一半。

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

  • 分代算法:根据对象存活周期的不同将内存划分为几块,一般是新生代和老年代,新生代基本采用复制算法,老年代采用标记整理算法。

13、http

13.1、https和http区别、有没有其他安全通道

1、HTTPS 协议需要到 CA (Certificate Authority,证书颁发机构)申请证书,一般免费证书较少,因而需要一定费用。(以前的网易官网是http,而网易邮箱是 https 。)

2、HTTP 是超文本传输协议,信息是明文传输,HTTPS 则是具有安全性的 SSL 加密传输协议。

3、HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

4、HTTP 的连接很简单,是无状态的。HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。(无状态的意思是其数据包的发送、传输和接收都是相互独立的。无连接的意思是指通信双方都不长久的维持对方的任何信息。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值