目录

一、Java 基础

1.JDK 和 JRE 有什么区别?

2.== 和 equals 的区别是什么?

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

4.final 在 java 中有什么作用?

5.JAVA 中的 Math.round(-1.5) 等于多少?

6.String 属于基础的数据类型吗?

7.java 中操作字符串都有哪些类?它们之间有什么区别?

8.String str="i"与 String str=new String("i")一样吗?

9.如何将字符串反转?

10.String 类的常用方法都有那些?

11.抽象类必须要有抽象方法吗?

12.普通类和抽象类有哪些区别?

13.抽象类能使用 final 修饰吗?

14.接口和抽象类有什么区别?

15.java 中 IO 流分为几种?

16.BIO、NIO、AIO 有什么区别?

17.Files的常用方法都有哪些?

18.重写和重载的区别

19.什么是多态

二、容器

1.java 容器都有哪些?

2.Collection 和 Collections 有什么区别?

3.List、Set、Map 之间的区别是什么?

4.HashMap 和 Hashtable 有什么区别?

5.如何决定使用 HashMap 还是 TreeMap?

6.说一下 HashMap 的实现原理?

7.说一下 HashSet 的实现原理?

8.ArrayList 和 LinkedList 的区别是什么?

9.如何实现数组和 List 之间的转换?

10.ArrayList 和 Vector 的区别是什么?

11.Array 和 ArrayList 有何区别?

12.在 Queue 中 poll()和 remove()有什么区别?

13.哪些集合类是线程安全的?

14.迭代器 Iterator 是什么?

15.Iterator 怎么使用?有什么特点?

16.Iterator 和 ListIterator 有什么区别?

17.怎么确保一个集合不能被修改?

三、多线程

1.并行和并发有什么区别?

2.线程和进程的区别?

3.守护线程是什么?

4.创建线程有哪几种方式?

5.说一下 runnable 和 callable 有什么区别?

6.线程有哪些状态?

7.sleep() 和 wait() 有什么区别?

8.notify()和 notifyAll()有什么区别?

9.线程的 run()和 start()有什么区别?

10.创建线程池有哪几种方式?

11.线程池都有哪些状态?

12.线程池中 submit()和 execute()方法有什么区别?

13.在 java 程序中怎么保证多线程的运行安全?

14.多线程锁的升级原理是什么?

15.什么是死锁?

16.怎么防止死锁?

17.ThreadLocal 是什么?有哪些使用场景?

18.说一下 synchronized 底层实现原理?

19.synchronized 和 volatile 的区别是什么?

20.synchronized 和 Lock 有什么区别?

21.synchronized 和 ReentrantLock 区别是什么?

22.说一下 atomic 的原理?

23.理解乐观锁和悲观锁

四、反射

1.什么是反射?

2.什么是 java 序列化?什么情况下需要序列化?

3.动态代理是什么?有哪些应用?

4.怎么实现动态代理?

         五、对象克隆

61.为什么要使用克隆?

62.如何实现对象克隆?

63.深克隆和浅克隆区别是什么? 

六、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.throw 和 throws 的区别?

2.final、finally、finalize 有什么区别?

3.try-catch-finally 中哪个部分可以省略?

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

5.常见的异常类有哪些?

八、网络

1.http 响应码 301 和 302 代表的是什么?有什么区别?

2.forward 和 redirect 的区别?

3.简述 tcp 和 udp的区别?

4.tcp 为什么要三次握手,两次不行吗?为什么?

5.说一下 tcp 粘包是怎么产生的?

6.OSI 的七层模型都有哪些?

7.get 和 post 请求有哪些区别?

8.如何实现跨域?

9.说一下 JSONP 实现原理?

10.单工、半双工、全双工

九、设计模式

1.说一下你熟悉的设计模式?

2.简单工厂和抽象工厂有什么区别?

十、Spring/Spring MVC

1.为什么要使用 spring?

2.解释一下什么是 aop?

3.解释一下什么是 ioc?

4.spring 有哪些主要模块?

5.spring 常用的注入方式有哪些?

6.spring 中的 bean 是线程安全的吗?

7.spring 支持几种 bean 的作用域?

8.spring 自动装配 bean 有哪些方式?

9.spring 事务实现方式有哪些?

10.说一下 spring 的事务隔离?

11.说一下 spring mvc 运行流程?

12.spring mvc 有哪些组件?

13.@RequestMapping 的作用是什么?

14.@Autowired 的作用是什么?

十一、Spring Boot/Spring Cloud

1.什么是 spring boot?

2.为什么要用 spring boot?

3.spring boot 核心配置文件是什么?

4.spring boot 配置文件有哪几种类型?它们有什么区别?

5.spring boot 有哪些方式可以实现热部署?

6.jpa 和 hibernate 有什么区别?

7.什么是 spring cloud?

8.spring cloud 断路器的作用是什么?

9.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

1.kafka 可以脱离 zookeeper 单独使用吗?为什么?

2.kafka 有几种数据保留的策略?

3.kafka 同时设置了 7 天和 10G 清除数据,到第五天的时候消息达到了 10G,这个时候 kafka 将如何处理?

4.什么情况会导致 kafka 运行变慢?

5.使用 kafka 集群需要注意什么?

十六、Zookeeper

1.zookeeper 是什么?

2.zookeeper 都有哪些功能?

3.zookeeper 有几种部署模式?

4.zookeeper 怎么保证主从节点的状态同步?

5.集群中为什么要有主节点?

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

7.说一下 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 的性能优化?

16.什么是数据库分区?

17.为什么要分区?

18.怎样分区?

十八、Redis

1.redis 是什么?都有哪些使用场景

2.redis 有哪些功能?

3.redis 和 memcache 有什么区别?

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.内存溢出、内存泄露、GC的基本概念

二十、题外话

1.你做过曾经最好的一个东西是什么

2.上一家公司为什么要离职

3.你还有什么想问的吗


一、Java 基础

1.JDK 和 JRE 有什么区别?

jdk:java development kit

jre:java runtime Environment

jdk是面向开发人员的,是开发工具包,包括开发人员需要用到的一些类。

jre是java运行时环境,包括java虚拟机等,是提供给使用java的人用的

2.== 和 equals 的区别是什么?

==比较的是两个对象,包括对象的地址位,如果比较的两个对象地址位不同,值相同也会返回false

equals比较的是两个字符串的值,只要值相同,就会返回true

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

不对,hashCode也是可以重写的,所以不一定。

反之,如果equals()相同,那么hashCode是一定相等的。

4.final 在 java 中有什么作用?

修饰类不可被继承;

修饰方法不可被重写;

修饰变量不能被修改。

5.JAVA 中的 Math.round(-1.5) 等于多少?

-1

向上取整Math.ceil();

向下取整Math.floor();

四舍五入Math.round(x); //==Math.floor(x+0.5)

6.String 属于基础的数据类型吗?

不属于,是final修饰的Java类。

java中的基本数据类型:byte、char、short、int、long、float、double、boolean

7.java 中操作字符串都有哪些类?它们之间有什么区别?

String、StringBuffer、StringBuilder

String类型的字符串是不可变的,StringBuffer和StringBuilder是可以对同一个对象做更新操作的

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

8.String str="i"与 String str=new String("i")一样吗?

不一样。他们不是同一个对象

前者如果定义多个变量都为相同值的话,会共用同一个地址,创建的对象应该放在了常量池中;

后者是创建了一个新的对象,放在的是堆内存中。

9.如何将字符串反转?

 使用StringBuffer 或 StringBuilder 的 reverse 成员方法。

10.String 类的常用方法都有那些?

"".toCharArray("");

"".charAt();

"".split();

"".indexOf();

"".equals();

"".contains();

"".length();

"".subString("");

"".replace("","");

11.抽象类必须要有抽象方法吗?

不是。抽象类可以没有抽象方法,但是如果你的一个类已经声明成了抽象类,即使这个类中没有抽象方法,它也不能再实例化,即不能直接构造一个该类的对象。如果一个类中有了一个抽象方法,那么这个类必须声明为抽象类,否则编译通不过。

12.普通类和抽象类有哪些区别?

普通类可以被继承,不能包含抽象方法,不可以被实现。

抽象类也可被继承,但是子类必须要实现父类中的抽象方法;

抽象类中的方法不能包含主体。

抽象类中的方法在扩展性和延伸性要比普通类的更好;

抽象类可以应用多态,普通类不可以。

13.抽象类能使用 final 修饰吗?

不能。

14.接口和抽象类有什么区别?

接口是要被实现的,抽象类是要被继承;

接口用interface修饰;抽象类使用abstract修饰;

两者均不能被实例化,方法都不包含主体;

一个类只能继承一个抽象类,但是可以实现多个接口。

15.java 中 IO 流分为几种?

字节流:InputStream、OutputStream

字符流:Reader、Writer

字节流是最基本的

  • 1.字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串;

  • 2.字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以。

读文本的时候用字符流,例如txt文件。读非文本文件的时候用字节流,例如mp3。

16.BIO、NIO、AIO 有什么区别?

BIO:Block IO 同步阻塞式 IO

NIO:Non IO 同步非阻塞 IO

AIO:Asynchronous IO  异步非阻塞IO

BIO是一个连接一个线程。JDK4之前的唯一选择
NIO是一个请求一个线程。JDK4之后开始支持,常见聊天服务器
AIO是一个有效请求一个线程。JDK7之后开始支持,常见相册服务器

17.Files的常用方法都有哪些?

file.getName();

file.getPath();

file.delete();

file.exits();

file.createDirectory();

file.copy();

file.move();

file.size();

file.read();

file.write();

18.重写和重载的区别

重载:必须有不同的参数列表;可以有不同的访问修饰符;可以抛出不同的异常;

重写:参数列表必须要与被重写的相同;返回的类型必须保持一致;修饰符和抛出的异常不能在被重写的方法之外

重写是父类与子类的关系,是垂直关系;重载是同一个类方法中的关系,是水平关系。

19.什么是多态

一种事物的多种表现形态就是多态,比如定义一个类为动物,那么动物可以被子类继承,从而实现具体动物的方法。

二、容器

1.java 容器都有哪些?

数组、Util下的容器:Collection(Set、List)、Map

2.Collection 和 Collections 有什么区别?

Collection是集合的接口,其实现类有List和Set;

Collections是工具类,包含许多有关集合操作的静态多态方法,可以直接使用。

3.List、Set、Map 之间的区别是什么?

List:有序集合、元素可重复

Set:元素不可重复,HashSet无序,LinkedHashSet按照插入排序,SortedSet可排序

Map:键值对集合,存储键、值之间的映射。key无序,唯一,value可重复

4.HashMap 和 Hashtable 有什么区别?

HashMap不是线程安全的,HashTable是线程安全的

HashMap允许Null Key和Null Value,HashTable不允许

5.如何决定使用 HashMap 还是 TreeMap?

如果需要得到一个有序的结果应该使用TreeMap

如果不需要排序最好选用HashMap,性能更优

6.说一下 HashMap 的实现原理?

HashMap基于Hash算法实现,通过put(key,value)存储,get(key)来获取value

当传入key时,HashMap会根据key,调用Hash(Object key)方法,计算出Hash值,根据Hash值将Value保存在Node对象里,Node对象保存在数组里。

当计算出的Hash值相同时,称为Hash冲突,HashMap的做法是用链表和红黑树存储相同Hash值的value

当Hash冲突的个数:小于等于8使用链表,大于8使用红黑树解决链表查询慢的问题。

7.说一下 HashSet 的实现原理?

HashSet是基于HashMap实现的,HashSet底层使用HashMap来保存所有元素,因此HashSet的操作相对比较简单,相关HashSet的操作,基本上都是直接调用底层的HashMap的相关方法来完成,HashSet不允许有重复的值,并且元素是无序的

8.ArrayList 和 LinkedList 的区别是什么?

ArrayList的数据结构是动态数组;LinkedList的数据结构是双向链表。

ArrayList比LinkedList在随机访问的时候效率要高,因为LinkedList是线性的数据结构,需要依次往后查找

在非首尾的增删操作,LinkedList要比ArrayList的效率要高,因为ArrayList在操作增删时要影响其他元素的下标

总结:需要频繁读取集合中的元素时,推荐使用ArrayList;插入和删除操作较多时,推荐使用LinkedList

9.如何实现数组和 List 之间的转换?

List转数组:String[] list = List.toArray(array);//array为List

数组转List:List list = java.util.Arrays.asList(array);//array为数组

10.ArrayList 和 Vector 的区别是什么?

相同点:都实现了List接口,都是有序集合

区别:Vector是线程安全的,ArrayList不是线程安全的;

当Vector或ArrayList中的元素超过它的初始大小时,Vector会将容量翻倍,而ArrayList只会将容量扩大50%

11.Array 和 ArrayList 有何区别?

Array类型的变量在声明时必须实例化;ArrayList可以只是先声明;

Array大小是固定的,而ArrayList的大小是动态变化的;

Array可以包含基本类型和对象类型,ArrayList只能包含对象类型

12.在 Queue 中 poll()和 remove()有什么区别?

Queue中poll()和remove()都是用来从队列头部删除一个元素;

在队列元素为空的情况下,remove()方法会抛出NoSuchElementException异常,而poll()只会返回null

13.哪些集合类是线程安全的?

  • Vector:相比ArrayList多了线程安全;
  • HashTable:相比HashMap多了线程安全;
  • ConcurrentHashMap:高效且线程安全;
  • Stack:继承于Vector,也是线程安全

14.迭代器 Iterator 是什么?

迭代器是一种设计模式,它是一个对象,可以遍历并选择序列中的对象。

15.Iterator 怎么使用?有什么特点?

next();

hashNext();

remove();

Iterator接口被Collection接口继承,Collection接口的iterator()方法返回一个iterator对象。

16.Iterator 和 ListIterator 有什么区别?

ListIterator有add()方法,可以向List中添加对象,而Iterator不能;

ListIterator有hasPrevious()和previous()方法,可以向前遍历,Iterator不能;

ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现;

ListIterator可以实现对对象的修改,使用set()实现;而Iterator只能遍历,不能修改

17.怎么确保一个集合不能被修改?

可以使用Collections.unmodifiableCollection(Collection c) 方法创建一个只读集合

这样改变集合的任何操作都会抛出Java. lang. UnsupportedOperationException异常。

三、多线程

1.并行和并发有什么区别?

并行是指两个或多个事件在同一时刻发生,是在不同实体上的多个事件;

并发是指两个或多个事件在同一时间间隔发生,是在同一个实体上的多个事件

2.线程和进程的区别?

进程是资源分配最小单位,线程是程序执行最小单位

每个进程都有相应的线程

进程有独立的地址空间,线程没有

线程是指处理机调度的基本单位

进程执行开销大,线程执行开销小

3.守护线程是什么?

在java线程开发中,有两种线程:User Thread(用户线程);Daemon Thread(守护线程)

普通用户进程在JVM退出时依然会继续执行,导致JVM并不能退出

普通进程可以使用setDaemon(true)方法升级为守护进程,守护进程在JVM退出时会自动结束运行。

守护线程拥有自动结束自己生命周期的特性,而非守护线程不具备这个特点

4.创建线程有哪几种方式?

继承Thread类并实现run方法,调用继承类的start方法开启线程;

通过实现Runnable接口,重写run方法,调用线程对象的start方法开启线程;

除此之外,还可以通过实现Callable接口,实现call方法,并用FutureTask类包装Callable对象开启线程。

5.说一下 runnable 和 callable 有什么区别?

实现Callable接口的任务线程能返回执行结果,而实现Runnable接口的任务线程并不能返回执行结果

Callable接口的call方法允许抛出异常,而Runnable接口的run方法的异常只能在内部消化,不能继续上抛

6.线程有哪些状态?

新建、就绪、运行、阻塞、死亡

7.sleep() 和 wait() 有什么区别?

sleep后程序不会释放同步锁,wait后程序会释放同步锁

sleep可以指定睡眠时间,自动唤醒,wait可以直接用notify唤醒

sleep的类是Thread,wait的类是Object

8.notify()和 notifyAll()有什么区别?

notify()方法会唤醒对象等待池中的一个线程,进入锁池;

notifyAll()方法会唤醒等待池中的所有线程,进入锁池

9.线程的 run()和 start()有什么区别?

调用start()方法是用来启动线程的,轮到该线程执行时,会自动调用run方法;

直接运行run方法无法达到启动多线程的目的,相当于调用Thread对象中的run方法

一个线程的start方法只能调用一次,多次调用会抛出异常;而run方法可以多次调用

10.创建线程池有哪几种方式?

主要使用Excutors提供的通用线程池创建方法,去创建不同配置的线程池

newCachedThreadPool();特点:用来处理大量短时间工作任务的线程池

newFixedThreadPool(int nThreads);特点:重用指定数目(nThreads)的线程

newSingleThreadExecutor();特点:工作线程数目限制为1

newSingleThreadScheduledExecutor()和newScheduledThreadPool(int corePoolSize)可以进行周期或定时性的工作调度

newWorkStealingPool(int parallelism);特点:JDK8以后才加入

11.线程池都有哪些状态?

RUNNING:线程池被创建,可以接收新线程

SHUTDOWN:线程池被关闭,不接收新线程,但是可以处理已有的线程。通过调用shutdown()方法;

STOP:线程池停止,不接受新线程,中断当前的线程,并且不会处理已有的线程。通过调用shutdownnow()方法;

TIDYING:线程池等待,当线程池处于SHUTDOWN或者STOP状态,并且任务队列为空且执行中任务为空则会转变;

TERMINATED:线程池彻底终止,线程池在TIDYING状态中执行完terminated()方法后就会转变为此状态。

12.线程池中 submit()和 execute()方法有什么区别?

execute() 参数 Runnable ;submit() 参数 (Runnable) 或 (Runnable 和 结果 T) 或 (Callable)

execute() 没有返回值;而 submit() 有返回值

submit()的返回值Future调用get方法时,可以捕获处理异常

13.在 java 程序中怎么保证多线程的运行安全?

JDK Atomic开头的原子类、synchronized、LOCK,可以解决原子性问题

synchronized、volatile、LOCK,可以解决可见性问题

Happens-Before 规则可以解决有序性问题

14.多线程锁的升级原理是什么?

锁的级别:无锁 => 偏向锁 => 轻量级锁 => 重量级锁

无锁:没有对资源进行锁定,所有线程都可以访问,但是只有一个能修改成功,其他的线程会不断尝试,直至修改成功。

偏向锁:对象的代码一直被同一线程执行,不存在多个线程竞争,偏向锁,指的就是偏向第一个加锁线程,该线程不会主动释放偏向锁,只有当其他线程尝试竞争偏向锁时才会被释放。

偏向锁的撤销,需要在某个时间点上没有字节码正在执行时,先暂停拥有偏向锁的线程,然后判断锁对象是否处于被锁定状态。如果线程不处于活动状态,则将对象头设置成无锁状态,并撤销偏向锁;

如果线程处于活动状态,升级为轻量级锁的状态。

轻量级锁:轻量级锁是指当锁是偏向锁的时候,被第二个线程 B 所访问,此时偏向锁就会升级为轻量级锁,线程 B 会通过自旋的形式尝试获取锁,线程不会阻塞,从而提高性能。当前只有一个等待线程,则该线程将通过自旋进行等待。但是当自旋超过一定的次数时,轻量级锁便会升级为重量级锁;当一个线程已持有锁,另一个线程在自旋,而此时又有第三个线程来访时,轻量级锁也会升级为重量级锁。

重量级锁:指当有一个线程获取锁之后,其余所有等待获取该锁的线程都会处于阻塞状态。

15.什么是死锁?

死锁是指两个或两个以上的进程在竞争资源的过程中造成的不可解堵塞。两个线程都在互相等待。

16.怎么防止死锁?

预防:资源一次性分配;可剥夺资源;资源有序分配;超时放弃

避免:银行家算法;

检测:为每个进程和每个资源建立唯一的ID,建立资源分配表和进程等待表

解除:剥夺资源;撤销进程

17.ThreadLocal 是什么?有哪些使用场景?

ThreadLocal是线程本地存储,在每个线程中都创建了一个ThreadLocalMap对象,每个线程可以访问自己内部ThreadLocal对象内的value。

经典的使用场景是为每个线程分配一个JDBC连接的Connection,这样就可以保证每个线程都在各自的Connection上进行数据库的操作,不会出现A线程关了B线程的Connection,还有Session管理等问题。

18.说一下 synchronized 底层实现原理?

同步代码块是通过monitorenter和monitorexit指令获取线程的执行权;

同步方法是通过加ACC_SYNCHRONIZED 标识实现线程的执行权的控制

19.synchronized 和 volatile 的区别是什么?

  • volatile本质是在告诉vm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;
    synchronize则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞。
  • volatile仅能实现变量的修改可见性,不能保证原子性;synchronize可以保证变量的修改可见性和原子性。
  • volatile不会造成线程的阻塞;synchronize可能会造成线程的阻塞。
  • volatile标记的变量不会被编译器优化,synchronize标记的变量可以被编译器优化

20.synchronized 和 Lock 有什么区别?

synchronized是关键字,属于jvm层面;Lock是具体类,是api层面的锁;

synchronized无法获取锁的状态,Lock可以判断;

synchronized用于少量同步,Lock用于大量同步。

21.synchronized 和 ReentrantLock 区别是什么?

synchronized代码执行结束后线程自动释放对锁的占用;Reentrantlock需要手动释放锁;

synchronized不可中断,除非抛出异常或者执行完成;Reentrantlock可中断;

synchronize非公平锁;Reentrantlock默认非公平锁,也可公平锁;

ReentrantLock用来实现分组唤醒需要唤醒的线程,可以精确唤醒,而不是像synchronized要么随机唤醒一个,要么唤醒全部线程。

22.说一下 atomic 的原理?

作用:多线程下将属性设置为atomic可以保证读取数据的一致性。

CAS(Compare And Swap),乐观锁的机制,先比较再交换,以实现原子性

23.理解乐观锁和悲观锁

乐观锁:认为每次去拿数据的时候别人不会修改,所以不会上锁,但是每次要拿数据的时候都会先判断数据是否被别人修改

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

使用场景:乐观锁使用于多读少写的应用类型,这样可以提高吞吐量;相反的情况则使用悲观锁

四、反射

1.什么是反射?

java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能成为java的反射机制。

2.什么是 java 序列化?什么情况下需要序列化?

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

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

当java对象需要在网络上传输或者持久化存储到文件中时,就需要对Java对象进行序列化处理。

序列化的实现:类实现Serializable接口。

3.动态代理是什么?有哪些应用?

在运行时,创建一个新的类,即创建动态代理,可以调用和扩展目标类的方法。动态代理的类是自动生成的。

应用:Spring的AOP,加事务,加权限,加日志

4.怎么实现动态代理?

基于jdk,需要实现InvocationHandler接口,重写invoke方法。

基于cglib,需要jar包依赖;

基于javassist

五、对象克隆

61.为什么要使用克隆?

如果直接使用=给对象赋值的话,那么两个对象其实指向的是同一个地址,其中一个值改变时,另一个也会随之改变。

62.如何实现对象克隆?

1、实现Coloneable接口并重写Object类中的clone()方法;

2、实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。

63.深克隆和浅克隆区别是什么?

深克隆:新旧对象不共享一个地址;

浅克隆:新旧对象共享一个地址,改变一个,另一个也会改变

六、Java Web

1.jsp 和 servlet 有什么区别?

Jsp:Java Server Page,是一种动态页面技术,其根本是一个简化的Servlet设计,用来封装产生动态网页的逻辑处理。

Servlet:服务器端的Java应用程序,具有独立于平台和协议的特性,可以生成动态的Web页面。它担当客户请求与服务器响应的中间层。

相同点:jsp经编译后就变成了Servlet,jsp本质就是servlet,jvm只能识别java的类,不能识别jsp代码,web容器将jsp的代码编译成jvm能够识别的java类。

2.jsp 有哪些内置对象?作用分别是什么?

  • request:用户端请求(get/post)
  • response:网页传回用户端的响应
  • pageContext:管理网页的属性
  • session:与请求有关的会话期
  • application servlet:正在执行的内容
  • out:用来传送回应的输出
  • config: servlet的架构部件
  • page JSP:网页本身
  • exception:针对错误网页,未捕捉的例外

3.说一下 jsp 的 4 种作用域?

  1. application:在所有应用程序中有效
  2. session:在当前会话中有效;
  3. request:在当前请求中有效;
  4. page:在当前页面有效

4.session 和 cookie 有什么区别?

  • 存储位置不同
    cookie的数据信息存放在客户端浏览器上
    session的数据信息存放在服务器上
  • 存储容量不同
    单个cookie保存的数据<=4Kb,一个站点最多保存20个cookie
    对于session来说没有上限
  • 存储方式不同
    cookie中只能保管ASCII字符串,并需要通过编码方式存储为Unicode字符或者二进制数据;
    session中能够存储任何类型的数据
  • 隐私策略不同
    cookie对客户端是可见的,所以它是不安全的;
    session存储在服务器上,对客户端是透明的,不会信息泄露
  • 有效期不同
    可以通过设置cookie的属性,使cookie长期有效;
    session不能达到长期有效的结果
  • 服务器压力不同
    cookie保存在客户端,不占用服务器资源
    session是保存在服务器的,如果并发访问的用户十分多,会产生很多的session,耗费大量的内存
  • 浏览器支持不同
    cookie是需要浏览器支持的,假如客户端禁用了cookie,或者不支持cookie,则会话跟踪会失效
    session只能在本窗口以及子窗口有效,而cookie可以为本浏览器上的一切窗口有效
  • 跨域支持不同
    cookie支持跨域名访问
    session不支持跨域名访问

5.说一下 session 的工作原理?

客户端登录完成之后,服务器会创建相应的session,session创建完成之后,会把session的id发送给客户端,客户端再存储到浏览器中。这样客户端每次访问服务器时,都会带着sessionid,服务器拿到sessionid之后,在内存找到与之对应的session就可以正常工作了。

6.如果客户端禁止 cookie,session 还能用吗?

如果浏览器禁用了cookie,那么客户端访问服务端时无法携带sessionid,服务端无法识别用户身份,便无法进行会话控制,session就会失效,但是可以通过其他办法实现:

  1. 通过URL重写,把sessionid作为参数追加的原URL中,后续的浏览器与服务器交互中携带session
  2. 服务器的返回数据中包含sessionid,浏览器发送请求时,携带sessionid参数

7.spring mvc 和 struts 的区别是什么?

  • 拦截机制不同
    Struts2是类级别的拦截,每次请求就会创建一个Action
    SpringMVC是方法级别的拦截,一个方法对应一个Request上下文。
  • 底层框架不同
    Struts2采用Filter实现,SpringMVC采用Servlet实现
  • 性能不同
    Struts2需要加载所有的属性值注入,SpringMVC实现了零配置,由于SpringMVC基于方法的拦截。
    所以,SpringMVC开发效率和性能高于Struts2
  • 配置方面
    SpringMVC 和 Spring 是无缝的,从这个项目的管理和安全上也比Struts2高。

8.如何避免 sql 注入?

SQL注入是Web开发中最常见的一种安全漏洞,可以用它来从数据库获取敏感信息,进行数据库的一系列非法操作。

  • 校验参数的数据格式是否合法
  • 对进入数据库的特殊字符进行转义处理,或编码转换
  • 预编译SQL,参数化查询方式,避免SQL拼接
  • 发布前利用工具进行SQL注入检测

9.什么是 XSS 攻击,如何避免?

XSS(Cross Site Scripting)跨站脚本攻击,它是Web程序中常见的漏洞。

原理:攻击者往web页面里插入恶意的HTML代码,当用户浏览该页面时,嵌入其这个你的HTML代码会被执行,从而达到恶意攻击用户的目的。

避免措施:

  • web页面中可由用户输入的地方,对输入的数据转义、过滤处理
  • 前端对HTML标签属性、css属性赋值的地方进行校验
  • 后台输出页面的时候,也需要对输出内容进行转义、过滤处理

10.什么是 CSRF 攻击,如何避免?

CSRF(Cross-site request forgery),也被称为one-click attack 或者 session riding,通常缩写为CSRF或XSRF,

是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

预防措施:

  • 验证HTTP Referer字段
  • 验证码
  • 添加token验证
  • 尽量使用post,限制get

七、异常

1.throw 和 throws 的区别?

throw:表示方法内抛出某种异常对象,如果异常对象不是RuntimeException,则需要在方法声明时加上该异常的抛出,即需要加上throws语句,或者在方法体内try catch异常,否则编译会报错;执行到throw语句则后面的语句块不再执行

throws:方法的定义上使用此关键字表示这个方法可能抛出某种异常,需要由方法的调用者进行异常处理。

2.final、finally、finalize 有什么区别?

final:修饰类时表示不能被继承;修饰方法时表示不能被重载;修饰变量时表示不能被修改。

finally:在异常处理时提供finally代码块来执行异常处理。

finalize:是方法名,java允许使用finalize()方法在垃圾收集器将对象从内存中清除之前做必要的清理工作。

3.try-catch-finally 中哪个部分可以省略?

catch 和 finally可以被省略其中一个,finally代码块是无论是否捕捉到异常,都会执行finally代码块的逻辑。

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

捕获到异常后,不会直接返回,会先执行完finally代码块的语句继续执行catch代码块中的return。

5.常见的异常类有哪些?

NullPointerException、SQLException、IndexOutOfBoundException、NumberFormatException、FileNotFoundException

IOException、IllegalArgumentException、NoSuchMethodException

八、网络

1.http 响应码 301 和 302 代表的是什么?有什么区别?

301:Moved Permanently ——被请求的资源已经永久移动到新位置

302:Found——被请求URL临时转移到新的URL

其他的响应码:

信息响应(100-199)、成功响应(200-299)、重定向(300-399)、客户端错误(400-499)、服务器错误(500-599)

2.forward 和 redirect 的区别?

  • redirect是客户端发起的请求;forward是服务端发起的请求
  • redirect浏览器显示被请求的URL;forward浏览器地址不显示被请求的URL
  • redirect重新开始一个request,原页面的request生命周期结束;
    forward另一个连接的时候,request变量是在其生命周期内的。
  • redirect实质上是两次HTTP请求;forward是一次请求

3.简述 tcp 和 udp的区别?

  • TCP是面向连接的,TCP提供可靠的服务,通过TCP连接传输的数据不会丢失,没有重复,并且按顺序到达。
    UDP是无连接的,没有可靠性,但是速度快,操作简单,要求系统资源较少,可以实现广播发送。
  • TCP是面向字节流的,UDP是面向报文的;TCP是全双工的可靠信道,UDP是不可靠信道

4.tcp 为什么要三次握手,两次不行吗?为什么?

  • 两次握手只能保证单向连接是畅通的。
  • 只有经过第三次握手,才能确保双向都可以收到对方发送的数据

5.说一下 tcp 粘包是怎么产生的?

TCP粘包:发送方发送的多个数据包,到接收方缓冲区首尾相连,粘成一包,被接收

产生原因:TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。

接收方原因:接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据。

6.OSI 的七层模型都有哪些?

OSI(Open System Interconnection Reference Model)开放式系统互联网通信

应用层、表达层、会话层、传输层、网络层、数据链路层、物理层

7.get 和 post 请求有哪些区别?

  • get是从服务器上获取数据;post是向服务器传送数据
  • get请求通过URL直接请求数据,数据信息可以在URL中看到;post请求是放在请求头中的,用户看不到;
  • get传送的数据量小,有限制,不能大于2kb,post传送的数据可以没有限制
  • get安全性比较低,post相对较安全

8.如何实现跨域?

  • 使用JSONP,利用了script不受同源策略的限制;
  • 代理跨域请求;
  • HTML5 postMessage方法;
  • 修改document.domain跨子域;
  • 基于HTML5 websocket协议

9.说一下 JSONP 实现原理?

同源:同协议、同主机、同端口号

json是一种数据格式,jsonp是一种数据调用的方式,带callback的json就是jsonp。

首先在客户端注册一个callback,然后把callback的名字传给服务器,此时,服务器先生成json数据,然后以JavaScript语法的方式,生成function,返回给客户端,客户端解析script,并执行callback函数。

简单的说,就是利用script标签没有跨域限制的"漏洞"来达到与第三方通讯的目的。

10.单工、半双工、全双工

单工:只支持数据在一个方向上传输;

半双工:允许数据在两个方向上传输,但在某一时刻,只允许数据在同一个方向上传输;

全双工:允许数据可以同时接收和发送信息,实现双向通信

九、设计模式

1.说一下你熟悉的设计模式?

单例模式:懒汉式(先声明变量,等到实际用到时再创建对象)饿汉式(直接创建对象)

工厂模式:工厂类可以根据条件生成不同的子类实例,这些子类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作。

适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起使用的类能够在一起工作。

模板方法模式:提供一个抽象类,将部分逻辑以具体方法或构造器的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑,不同的子类可以从不同的方式实现这些抽象方法,从而实现不同的业务逻辑。

2.简单工厂和抽象工厂有什么区别?

  • 简单工厂
    由一个工厂对象创建产品实例,简单工厂模式的工厂类一般是使用静态方法,通过不同的参数创建不同的对象的实例。可以生产结构中的任意产品,不能增加新的产品。
  • 抽象工厂
    提供一个创建一系列相关或相互依赖对象的接口,而无需制定他们具体的类,生产多个系列产品,生产不同产品族的全部产品,不能新增产品,可以新增产品族。

十、Spring/Spring MVC

1.为什么要使用 spring?

  • 方便解耦,便于开发
  • 支持aop编程
  • 声明式事务的支持
  • 方便程序的测试
  • 方便集成各种优秀的框架
  • 降低JavaEE API的使用难度

2.解释一下什么是 aop?

AOP(Aspect Oriented Programming)面向切面编程

通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

通俗的解释:在运行时,动态的将代码切入到类的指定方法、指定位置的编程思想就是面向切面的编程。

3.解释一下什么是 ioc?

IOC(Inversion Of Control)控制反转

它是一种设计思想,在java开发中,将设计好的对象交给容器控制,而不是显示地用代码进行对象的创建。

把创建和查找依赖对象的控制权交给IOC容器,由IOC容器进行注入、组合对象,这样对象与对象之间是松耦合,便于测试,功能可复用,使得程序的整个体系结构可维护,灵活性、扩展性变高。

4.spring 有哪些主要模块?

  1. Spring Core
    框架的基础部分,提供IOC容器,对bean进行管理。
  2. Spring Context
    基于bean,提供上下文信息,扩展出JNDI、EJB、电子邮件、国际化、校验和调度等功能。
  3. Spring DAO
    提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码,还提供了声明性事务管理方法
  4. Spring ORM
    提供了常用的“对象/关系”映射APIs的集成层。其中包括JPA、JDO、hibernate、Mybatis等。
  5. Spring AOP
    提供了面向切面编程。
  6. Spring Web
    提供了基础的Web开发的上下文信息,可与其他Web进行集成。
  7. Spring Web MVC
    提供了Web应用的Model-View-Controller 全功能实现。

5.spring 常用的注入方式有哪些?

构造方法注入、setter注入、基于注解的注入

6.spring 中的 bean 是线程安全的吗?

Spring 中的Bean本身不具备线程安全的特性

7.spring 支持几种 bean 的作用域?

  • singleton:单例,默认作用域
  • prototype:原型,每次创建一个新对象
  • request:请求,每次Http请求创建一个新对象,适用于WebApplicationContext环境下
  • session:会话,同一个会话共享一个实例,不同会话使用不同的实例
  • global-session:全局会话,所有会话共享一个实例

8.spring 自动装配 bean 有哪些方式?

  • default:默认的方式和no方式一样
  • no:不自动装配,需要使用<ref/>节点或参数
  • byName:根据名称进行装配
  • byType:根据类型进行装配
  • constructor:根据构造函数进行装配

9.spring 事务实现方式有哪些?

  • 编程式事务管理,需要在代码中调用beginTransaction()、commit()、rolback()等事务管理相关的方法
  • 基于TransactionProxyFactoryBean的声明式事务管理
  • 基于@Transactional的声明式事务管理
  • 基于Aspectj AOP配置事务

10.说一下 spring 的事务隔离?

  • 事务产生的问题
名称数据的状态实际行为产生原因
脏读未提交打算提交但是数据回滚了,读取了提交的数据数据的读取
不可重复读已提交读取了修改前的数据数据的修改
幻读已提交读取了插入前的数据

数据的插入

  • 事务隔离级别

名称

结果脏读不可重复读幻读
Read UnCommitted(读未提交)什么都不解决
Read Committed(读提交)解决了脏读的问题
Repeatable Read(重复读)解决了不可重复读
Serializable(序列化)解决所有问题

11.说一下 spring mvc 运行流程?

  • 用户向服务器发送请求,请求被 Spring 前端控制 Servelt DispatcherServlet 捕获。(捕获)
  • DispatcherServlet对请求 URL进行解析,得到请求资源标识符(URI)。然后根据该  URI,调用 HandlerMapping获得该Handler配置的所有相关的对象(包括  Handler对象以及   Handler对象对应的拦截器),最后以 HandlerExecutionChain对象的形式返回;(查找   handler)
  • DispatcherServlet  根据获得的 Handler,选择一个合适的  HandlerAdapter。提取Request 中的模型数据,填充 Handler 入参,开始执行 Handler(Controller), Handler执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象(执行 handler)
  • DispatcherServlet  根据返回的 ModelAndView,选择一个适合的 ViewResolver(必须是已经注册到 Spring 容器中的 ViewResolver) (选择 ViewResolver)
  • 通过 ViewResolver 结合 Model 和 View,来渲染视图,DispatcherServlet 将渲染结果返回给客户端。(渲染返回

总结:核心控制器捕获请求、查找Handler、执行Handler、选择ViewResolver,通过ViewResolver渲染视图并返回

这里写图片描述

12.spring mvc 有哪些组件?

  • 前端控制器(DispatcherServlet)
  • 处理器映射器(HandlerMapping)
  • 处理器适配器(HandlerAdapter)
  • 拦截器(HandlerInterceptor)
  • 视图解析器(ViewResolver)
  • 文件上传处理器(MultipartResolver)
  • 异常处理器(HandlerExceptionResolver)
  • 消息转换器(HttpMessageConverter)
  • ...

13.@RequestMapping 的作用是什么?

@RequestMapping是一个用来处理请求地址映射的注解,可用于类或者方法上,用来标识 http 请求地址与 Controller 类的方法之间的映射。

14.@Autowired 的作用是什么?

@Autowired是一个注解,他可以对类成员变量、方法及构造函数进行标注,让spring完成bean自动装配的工作。

十一、Spring Boot/Spring Cloud

1.什么是 spring boot?

SpringBoot是Spring开源框架下的子项目,是Spring的一站式解决方案,主要是简化了spring的使用难度,降低了对配置文件的要求,使得开发人员更容易上手。

2.为什么要用 spring boot?

  • 简化了Spring配置文件
  • 没有代码和XML文件的生成
  • 内置tomcat
  • 能够独立运行
  • 简化监控

3.spring boot 核心配置文件是什么?

SpringBoot有两种类型的配置文件,application和Bootstrap文件

4.spring boot 配置文件有哪几种类型?它们有什么区别?

SpringBoot会自动加载classpath下的这两个文件,文件格式为properties或yml格式

  • *.properties 是 key = value 的形式
  • *.yml 是 key : value 的形式

Bootstrap配置文件是系统级别的,用来加载外部配置,也可以用来定义系统不会变化的属性,.bootstrap文件的加载要先于application文件

5.spring boot 有哪些方式可以实现热部署?

  • Spring Loaded
  • spring-boot-devtools
  • JRebel插件
  • 使用调试模式Debug实现热部署
  • 模板热部署

6.jpa 和 hibernate 有什么区别?

JPA(Java Persistence API)

  • Hibernate是JPA规范的一个实现。
  • hibernate有JPA没有的特性
  • hibernate的效率更高
  • JPA有更好的移植性,通用性

7.什么是 spring cloud?

spring cloud是在SpringBoot基础上构建的,用于快速构建分布式系统的通用模式的工具集。

SpringCloud是一个微服务框架,提供全套的分布式系统解决方案。

8.spring cloud 断路器的作用是什么?

当一个服务调用另一个服务,由于网络原因或者自身原因出现问题时,调用者就会等待被调用者的响应,当更多的服务请求到这些资源时,导致更多的请求等待,这样就会发生连锁效应,断路器就是为了解决这个问题。

  • 全开:
    一定时间内,达到一定的次数无法调用,并且多次检测没有恢复的迹象,断路器完全打开,那么下次请求就不会请求到该服务
  • 半开:
    短时间内有恢复迹象,断路器会将部分请求发给该服务,当能正常调用时,断路器关闭。
  • 关闭:
    当服务一直处于正常状态,能正常调用,断路器关闭

9.spring cloud 的核心组件有哪些?

  1. 服务发现——Netflix Eureka
  2. 客户端负载均衡——Netflix Ribbon
  3. 断路器——Netflix Hystrix
  4. 服务网关——Netflix Zuul
  5. 分布式配置——Spring Cloud Config

10.SpringBoot的启动流程

主要分为两个步骤:

1、创建SpringApplication对象。

2、调用SpringApplication对象的run()方法实现启动,并且返回当前容器的上下文。

详细步骤:

一、创建SpringApplication对象,SpringBoot容器的初始化操作。

二、获取当前应用的启动类型。

三、setInitializers读取springboot包下的META-INF/spring.factories获取到对应的ApplicationContextInitializer装配到集合中

四、setListeners读取springboot包下面的META-INF/spring.factories获取到对应的ApplicationListener装配到集合中

五、mainApplicationClass获取当前运行的主函数

六、调用SpringApplication的run()方法实现启动

七、stopWatch.start();开始记录项目的启动时间

八、getRunListeners(args);读取META-INF/spring.factories,将SpringApplicationRunListeners类型存入带集合中

九、listeners.starting();循环调用starting()方法

十、ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);

listeners.environmentPrepared(environment);循环读取配置文件到springboot容器中,因为配置文件可以自定义,就会存在多个。

十一、Banner printedBanner = printBanner(environment);打印Springboot启动标志

十二、context = createApplicationContext();创建springboot上下文

十三、prepareContext(context, environment, listeners, applicationArguments, printedBanner);为springboot上下文设置environment属性。

十四、refreshContext(context);刷新上下文

十五、开始创建Tomcat容器

十六、开始加载SpringMVC

十七、afterRefresh(context,applicationArguments);定义一个空的模板给其他子类实现重写

十八、listeners.started(context);使用广播和回调机制通知监听器springboot容器启动成功

十九、listeners.running(context);使用广播和回调机制通知监听器springboot容器已成功running

二十、最后返回当前的上下文

十二、Hibernate

1.为什么要使用 hibernate?

  • 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码
  • 基于jdbc的主流持久化框架,是一个优秀的ORM实现,很大程度的简化了dao层的编码工作
  • 使用java的反射机制
  • 性能好,是一个轻量级框架,映射灵活,支持很多关系型数据库,从一对一到多对多的各种复杂关系

2.什么是 ORM 框架?

ORM(Object Relation Mapping)对象关系映射

通过类与数据库表的映射关系,将对象持久化到数据库

常见的ORM框架有Hibernate、Mybatis、EclipseLink、JFinal

3.hibernate 中如何在控制台查看打印的 sql 语句?

在hibernate的配置文件中添加配置:hibernate.show_sql=true

4.hibernate 有几种查询方式?

HQL,QBC(Query By Criteria),原生SQL查询

5.hibernate 实体类可以被定义为 final 吗?

可以,但是这种做法不好。因为Hibernate会使用代理模式在延迟关联的情况下提高性能,如果把实体类定义成final类之后,因为java不允许对final类进行扩展,所以hibernate就无法再使用代理了,从而影响性能。

6.在 hibernate 中使用 Integer 和 int 做映射有什么区别?

如果使用基本类型变量int,如果数据库中对应的存储数据是null,使用PO类进行获取数据会出现类型转换异常。

如果使用你的是对象类型Integer则不会报错。

7.hibernate 是如何工作的?

  1. 读取并解析配置
  2. 读取并解析映射信息
  3. 创建Session Factory
  4. 打开Session
  5. 创建事务Transaction
  6. 持久化操作
  7. 提交事务
  8. 关闭Session
  9. 关闭SessionFactory

8.get()和 load()的区别?

get:get方法被调用时会立即发出SQL语句

load:当调用load方法的时候会返回一个目标对象的代理对象,在这个代理对象中只存储了目标对象的ID值,只有当调用除ID值以外的属性值的时候才会发出SQL查询。

9.说一下 hibernate 的缓存机制?

Hibernate中的缓存分为一级缓存和二级缓存

一级缓存就是Session级别的缓存,在事务范围内有效,内置的不能被卸载。

二级缓存是SessionFactory级别的缓存,从应用启动到应用结束有效,是可选的。默认没有二级缓存,需要手动开启。

10.hibernate 对象有哪些状态?

  • Transient(瞬时):对象刚new出来,还没设ID,设了其他值
  • Persistent(持久):调用了save()、saveOrUpdate(),就变成Persistent
  • Detached(托管):当session close()完之后,变成Detached

11.在 hibernate 中 getCurrentSession 和 openSession 的区别是什么?

openSession:每次使用都是打开一个新的对象,而且使用完需要调用close方法关闭session

getCurrenctSession:如果已经有session,就使用旧的,如果没有再打开新的。

一般情况下都是使用getCurrenctSession

12.hibernate 实体类必须要有无参构造函数吗?为什么?

必须,因为hibernate框架会调用这个默认构造方法来构造实例对象。

如果没有提供任何构造方法,虚拟机会自动提供默认构造方法,如果开发人员提供了其他有参数的构造方法的话,虚拟机就不再提供默认构造方法,这时必须手动把无参构造器写出来。

十三、Mybatis

1.mybatis 中 #{}和 ${}的区别是什么?

#{}是预编译处理,${}是字符串替换

使用#{}可以预防SQL注入

2.mybatis 有几种分页方式?

  • 数组分页
  • SQL分页
  • 拦截器分页
  • RowBounds分页

3.RowBounds 是一次性查询全部结果吗?为什么?

不是。Mybatis是JDBC的封装,在jdbc驱动中有一个Fetch Size的配置,它规定了每次最多从数据库查询多少条数据,假如要查询更多的数据,它会在执行next的时候,去查询更多的数据。这样可以有效的防止内存溢出。

4.mybatis 逻辑分页和物理分页的区别是什么?

  • 逻辑分页是一次性查询很多数据,然后再在结果中检索分页的数据,这样做的弊端是需要消耗大量的内存,有内存溢出的风险,对数据库压力较大。
  • 物理分页是从数据库查询指定条数的数据,弥补了一次性查出所有数据的种种缺点。

5.mybatis 是否支持延迟加载?延迟加载的原理是什么?

支持。设置lazyLoadingEnable=true即可

延迟加载的原理是调用的时候触发加载,而不是在初始化的时候就加载信息。

6.说一下 mybatis 的一级缓存和二级缓存?

  • 一级缓存:一级缓存的作用域是一个sqlsession对象,第一次查询数据时会保存到sqlsession对象中,第二次如果查询相同的数据,则直接从sqlsession获取,直接获取的前提是这期间这个对象中的数据没有改变,即增删改操作;反之,若有改变,则会自动清除sqlsession缓存,重新进行查询,这并不代表我们关闭了sqlsession。
  • 二级缓存:二级缓存是多个sqlsession共享的,是sqlsession factory 级别的,根据 mapper 的 namespace 划分区域 的,相同 namespace 的 mapper 查询的数据缓存在同一个区域,如果使用 mapper 代理方法每个 mapper 的 namespace 都不同,此时可以理解为二级缓存区域是根据 mapper 划分。每次查询会先从缓存区域查找,如果找不到则从数据库查询,并将查询到数据写入缓存。Mybatis 内部存储缓存使用一个 HashMap,key 为 hashCode+sqlId+Sql 语句。value 为从查询出来映射生成的 java 对象。sqlSession 执行 insert、update、delete 等操作 commit 提交后会清空缓存区域,防止脏读数据。

缓存更新机制:当某一个作用域(一级缓存Session/二级缓存Mapper)进行了C/U/D操作后,默认该作用域下所有select中的缓存将被clear。

7.mybatis 和 hibernate 的区别有哪些?

  • Mybatis入门比较简单,使用门槛也更低
  • SQL直接优化上,Mybatis要比Hibernate方便
  • Hibernate数据库移植性远大于Mybatis
  • 缓存机制上,hibernate要比mybatis更好一些

8.mybatis 有哪些执行器(Executor)?

  • SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。
  • ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。
  • BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

9.mybatis 分页插件的实现原理是什么?

分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

10.mybatis 如何编写一个自定义插件?

Mybatis自定义插件主要借助Mybatis四大对象:
   (Executor、StatementHandler 、ParameterHandler 、ResultSetHandler)进行拦截 

Executor:拦截执行器的方法(log记录) 
StatementHandler:拦截Sql语法构建的处理 
ParameterHandler:拦截参数的处理 
ResultSetHandler:拦截结果集的处理

十四、RabbitMQ

1.rabbitmq 的使用场景有哪些?

  • 跨系统的异步通信,所有需要异步交互的地方都可以使消息队列
  • 多个应用之间的耦合
  • 应用内的同步变异步
  • 消息驱动的架构
  • 跨局域网,甚至跨城市的通讯

2.rabbitmq 有哪些重要的角色?

生产者:消息的创建者,负责创建和推送消息到消息服务器

消费者:消息的接收方,用于处理数据和确认消息

代理:RabbitMQ本身,本身不生产消息,只是扮演“快递员”的角色

3.rabbitmq 有哪些重要的组件?

  • ConnectionFactory(连接管理器):应用程序与RabbitMQ之间建立连接的管理器,程序代码中使用。
  • Chanel(信道):消息推送使用的通道。
  • Exchange(交换器):用于接收、分配消息。
  • Queue(队列):用于存储生产者的消息。
  • RoutingKey(路由键):用于把生产者的数据分配到交换器上。
  • BindingKey(绑定键):用于把交换器的消息绑定到队列上。

4.rabbitmq 中 vhost 的作用是什么?

vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。其内部均含有独立的 queue、exchange 和 binding 等,但最最重要的是,其拥有独立的权限系统,可以做到 vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段(一个典型的例子就是不同的应用可以跑在不同的 vhost 中)。

5.rabbitmq 的消息是怎么发送的?

首先客户端必须连接到 RabbitMQ 服务器才能发布和消费消息,客户端和 rabbit server 之间会创建一个 tcp 连接,一旦 tcp 打开并通过了认证(认证就是你发送给 rabbit 服务器的用户名和密码),你的客户端和 RabbitMQ 就创建了一条 amqp 信道(channel),信道是创建在“真实” tcp 上的虚拟连接,amqp 命令都是通过信道发送出去的,每个信道都会有一个唯一的 id,不论是发布消息,订阅队列都是通过这个信道完成的。

6.rabbitmq 怎么保证消息的稳定性?

提供了事务的功能

通过将channel设置为confirm(确认)模式

7.rabbitmq 怎么避免消息丢失?

  • 消息持久化
  • ACK确认机制
  • 设置集群镜像模式
  • 消息补偿机制

8.要保证消息持久化成功的条件有哪些?

  • 声明队列必须设置持久化durable设置为true
  • 消息推送投递模式必须设置持久化,deliveryMode设置为2(持久)
  • 消息已经到达持久化交换器
  • 消息已经到达持久化队列

9.rabbitmq 持久化有什么缺点?

缺点是降低了服务器的吞吐量,因为使用的是磁盘而非内存存储,从而降低了吞吐量。

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

10.rabbitmq 有几种广播类型?

  • fanout::所有bind到此exchange的queue都可以接收消息(纯广播,绑定到RabbitMQ的接收者都能收到消息);
  • direct::通过routingKey和exchange决定的那个唯一的queue可以接收消息;
  • topic:所有符合routingKey(此时可以是一个表达式)的routingKey所bind的queue可以接收消息

11.rabbitmq 怎么实现延迟消息队列?

消息过期后进入死信交换器,再由交换器转发到延迟消费队列,实现延迟功能

使用RabbitMQ-delayed-message-exchange 插件实现延迟功能。

12.rabbitmq 集群有什么用?

  • 高可用:某个服务器出现问题,整个RabbitMQ还可以继续使用
  • 高容量:集群可以承载更多的消息量

13.rabbitmq 节点的类型有哪些?

  • 磁盘节点:消息会存储到磁盘
  • 内存节点:消息都存储在内存中,重启服务器消息会丢失,但性能要高于磁盘类型

14.rabbitmq 集群搭建需要注意哪些问题?

  • 各节点之间使用“–link”连接,此属性不能忽略。
  • 各节点使用的 erlang cookie 值必须相同,此值相当于“秘钥”的功能,用于各节点的认证。
  • 整个集群中必须包含一个磁盘节点。

15.rabbitmq 每个节点是其他节点的完整拷贝吗?为什么?

不是,原因有以下两个:

  • 存储空间的考虑:如果每个节点都拥有所有队列的完全拷贝,这样新增节点不但没有新增存储空间,反而增加了更多的冗余数据;
  • 性能的考虑:如果每条消息都需要完整拷贝到每一个集群节点,那新增节点并没有提升处理消息的能力,最多是保持和单节点相同的性能甚至是更糟。

16.rabbitmq 集群中唯一一个磁盘节点崩溃了会发生什么情况?

  • 不能创建队列
  • 不能创建交换器
  • 不能创建绑定
  • 不能添加用户
  • 不能更改权限
  • 不能添加和删除集群节点

唯一磁盘节点崩溃了,集群是可以保持运行的,但是不能更改任何东西。

17.rabbitmq 对集群节点停止顺序有要求吗?

RabbitMQ 对集群的停止的顺序是有要求的,应该先关闭内存节点,最后再关闭磁盘节点。如果顺序恰好相反的话,可能会造成消息的丢失。

十五、Kafka

1.kafka 可以脱离 zookeeper 单独使用吗?为什么?

kafka不能脱离zookper单独使用,因为kafka使用zookper管理和协调kafka的节点服务器。

2.kafka 有几种数据保留的策略?

按照过期时间保留;按照存储的消息大小保留

3.kafka 同时设置了 7 天和 10G 清除数据,到第五天的时候消息达到了 10G,这个时候 kafka 将如何处理?

执行数据清除工作,时间和大小不论哪个满足条件,都会清空数据。

4.什么情况会导致 kafka 运行变慢?

  • CPU性能瓶颈
  • 磁盘读写瓶颈
  • 网络瓶颈

5.使用 kafka 集群需要注意什么?

集群的数量不是越多越好,最好不要超过 7 个,因为节点越多,消息复制需要的时间就越长,整个群组的吞吐量就越低。
集群数量最好是单数,因为超过一半故障集群就不能用了,设置为单数容错率更高。

十六、Zookeeper

1.zookeeper 是什么?

zookper是一个分布式的,开放源码的分布式应用程序协调服务。是 google chubby 的开源实现,是 hadoop 和 hbase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

2.zookeeper 都有哪些功能?

  • 集群管理:监控节点存活状态、运行请求等。
  • 主节点选举:主节点挂掉了之后可以从备用的节点开始新一轮选主,主节点选举说的就是这个选举的过程,使用 zookeeper 可以协助完成这个过程。
  • 分布式锁:zookeeper 提供两种锁:独占锁、共享锁。独占锁即一次只能有一个线程使用资源,共享锁是读锁共享,读写互斥,即可以有多线线程同时读同一个资源,如果要使用写锁也只能有一个线程使用。zookeeper可以对分布式锁进行控制。
  • 命名服务:在分布式系统中,通过使用命名服务,客户端应用能够根据指定名字来获取资源或服务的地址,提供者等信息。

3.zookeeper 有几种部署模式?

  • 单机部署:一台机器上运行
  • 集群部署:多台机器运行
  • 伪集群部署:一台机器启动多个zookper实例运行

4.zookeeper 怎么保证主从节点的状态同步?

zookeeper 的核心是原子广播,这个机制保证了各个 server 之间的同步。实现这个机制的协议叫做 zab 协议。 zab 协议有两种模式,分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,zab 就进入了恢复模式,当领导者被选举出来,且大多数 server 完成了和 leader 的状态同步以后,恢复模式就结束了。状态同步保证了 leader 和 server 具有相同的系统状态。

5.集群中为什么要有主节点?

在分布式环境中,有些业务逻辑只需要集群中的某一台机器进行执行,其他的机器可以共享这个结果,这样可以大大减少重复计算,提高性能,所以就需要主节点。

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

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

7.说一下 zookeeper 的通知机制?

客户端会对某个 znode 建立一个 watcher 事件,当该 znode 发生变化时,这些客户端会收到 zookeeper 的通知,然后客户端可以根据 znode 变化来做出业务上的改变。

十七、MySql

1.数据库的三范式是什么?

  • 第一范式:强调的是列的原子性,即数据库表的每一列都是不可分割的原子数据项
  • 第二范式:要求实体的属性完全依赖于主关键字,所谓完全依赖是指不能存在仅依赖主关键字一部分的属性。
  • 第三范式:任何非主属性不依赖于其他非主属性

2.一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了一条数据,此时 id 是几?

表类型如果是MyISAM,那ID就是8

表类型如果是InnoDB,那ID就是6

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

select version()

4.说一下 ACID 是什么?

  • Atomicity(原子性):一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。
  • Consistency(一致性):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。
  • Isolation(隔离性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
  • Durability(持久性):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

5.char 和 varchar 的区别是什么?

  • char(n) :固定长度类型。优点:效率高;缺点:占用空间;
  • varchar(n) :可变长度,存储的值是每个值占用的字节再加上一个用来记录其长度的字节的长度。

所以,从空间上考虑 varcahr 比较合适;从效率上考虑 char 比较合适,二者使用需要权衡。

6.float 和 double 的区别是什么?

  • float 最多可以存储 8 位的十进制数,并在内存中占 4 字节。
  • double 最可可以存储 16 位的十进制数,并在内存中占 8 字节。

7.mysql 的内连接、左连接、右连接有什么区别?

  • 内连接是把匹配的关联数据显示出来;
  • 左连接是左边的表全部显示出来,右边的表显示出符合条件的数据,如果没有就显示为NULL
  • 右连接正好相反。

8.mysql 索引是怎么实现的?

索引是满足某种特定查找算法的数据结构,而这些数据结构会以某种方式指向数据,从而实现高效查找数据。

目前主流的数据库引擎的索引都是 B+ 树实现的,B+ 树的搜索效率,可以到达二分法的性能,找到数据区域之后就找到了完整的数据结构了,所有索引的性能也是更好的。

9.怎么验证 mysql 的索引是否满足需求?

  • explain select * from table where column=''

使用 explain 查看 SQL 是如何执行查询语句的,从而分析你的索引是否满足需求。

10.说一下数据库的事务隔离?

MySQL 的事务隔离是在 MySQL. ini 配置文件里添加的,在文件的最后添加:transaction-isolation = REPEATABLE-READ

可用的配置值:READ-UNCOMMITTED、READ-COMMITTED、REPEATABLE-READ、SERIALIZABLE

  • READ-UNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就可被其他事务读取(会出现幻读、脏读、不可重复读)。
  • READ-COMMITTED:提交读,一个事务提交后才能被其他事务读取到(会造成幻读、不可重复读)。
  • REPEATABLE-READ:可重复读,默认级别,保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(会造成幻读)。
  • SERIALIZABLE:序列化,代价最高最可靠的隔离级别,该隔离级别能防止脏读、不可重复读、幻读。
  • 脏读 :表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插入记录 A,此时该事务还未提交,然后另一个事务尝试读取到了记录 A。
  • 不可重复读 :是指在一个事务内,多次读同一数据。
  • 幻读 :指同一个事务内多次查询返回的结果集不一样。比如同一个事务 A 第一次查询时候有 n 条记录,但是第二次同等条件下查询却有 n+1 条记录,这就好像产生了幻觉。发生幻读的原因也是另外一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记录的数据内容被修改了,所有数据行的记录就变多或者变少了。

11.说一下 mysql 常用的引擎?

Mysql在V5.1之前默认存储引擎是MyISAM;在此之后默认存储引擎是InnoDB

  • InnoDB 引擎:
            提供了ACID事务的支持;
            提供了行级锁和外键的约束;
            不支持全文搜索,启动较慢;
            不会保存表的行数,执行 select count(*) from table 指令时,需要进行扫描全表;
            效率高,在高并发场景下使用。
  • MyIASM 引擎:
            不提供ACID事务的支持;
            不提供行级锁和外键的约束;
            保存了表的行数,执行select count(*) 的时候,可以直接读取保存的结果;
            不需要事务支持可以选择MyIASM引擎。
  • InnoDB 引擎提供了对数据库 acid 事务的支持,并且还提供了行级锁和外键的约束,它的设计的目标就是处理大数据容量的数据库系统。MySQL 运行的时候,InnoDB 会在内存中建立缓冲池,用于缓冲数据和索引。但是该引擎是不支持全文搜索,同时启动的也比较慢,它不会保存表的行数,所以当执行 select count(*) from table 指令的时候,需要进行扫描全表。由于锁的粒度小,写操作不会锁定全表,所以在并发度较高的场景下使用可以提升效率。
  • MyIASM 引擎:不提供事务的支持,也不支持行级锁和外键。因此当执行插入和更新语句时,即执行写操作的时候需要锁定这个表,所以会导致效率降低。不过和 InnoDB 不同的是,MyIASM 引擎是保存了表的行数,于是当进行 select count(*) from table 语句时,可以直接的读取已经保存的值而不需要进行扫描全表。所以,如果表的读操作远远多于写操作时,并且不需要事务的支持的,可以将 MyIASM 作为数据库引擎的首选。

12.说一下 mysql 的行锁和表锁?

MyISAM 只支持表锁,InnoDB 支持表锁和行锁,默认为行锁。

  • 表级锁:开销小,加锁快,不会出现死锁。
                  锁力度大,发生锁冲突的概率高,并发量最低。
  • 行级锁:开销大,加锁慢,会出现死锁。
                  锁力度小,发生锁冲突的概率小,并发度最高。

13.说一下乐观锁和悲观锁?

  • 乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。
  • 悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。

14.mysql 问题排查都有哪些手段?

  • 使用 show processlist 命令查看当前所有连接信息。
  • 使用 explain 命令查询 SQL 语句执行计划。
  • 开启慢查询日志,查看慢查询的 SQL。

15.如何做 mysql 的性能优化?

  • 为搜索字段创建索引。
  • 避免使用 select *,列出需要查询的字段。
  • 垂直分割分表。
  • 选择正确的存储引擎。

16.什么是数据库分区?

根据一定逻辑规则,将一个表拆成多个更小更容易管理的部分。

其主要目的是为了在特定的SQL操作中减少数据读写的总量以缩减响应时间。

查看是否支持分区命令:

  • 5.6以下的版本:show variables like '%partition%';
  • 5.6以上的版本:show plugins;   当看到有partition并且status是active时表示支持。

17.为什么要分区?

  • 分区可以在一个表中存储比单个磁盘或文件系统分区上的数据更多的数据,因为我们可以将分区表存储在不同物理磁盘上
  • 对已过期或者不需要保存的数据,可以通过删除与这些数据有关的分区来快速删除数据,他的效率远比delete高;
  • 优化查询,在where子句中包含分区条件时,可以只扫描必要的一个或者多个分区来提高查询效率;
    例如:SELECT * FROM t PARTITION(p0,p1)WHERE c <5  仅选择与WHERE条件匹配的分区p0和p1中的那些行。
    在这种情况下,MySQL不检查表t的任何其他分区;
  • 凭借在多个磁盘上传播数据,实现更高的查询吞吐量。

注:一个表最多只能有1024个分区,同一个分区表的所有分区必须使用相同的存储引擎

18.怎样分区?

  • RANGE分区:基于一个给定连续区间范围,把数据分配到不同的分区;
  • LIST分区:类似RANGE分区,区别在LIST分区是基于枚举出的值列表分区,RANGE是基于给定连续区间范围分区;
  • HASH分区:基于用户定义的表达式返回值来选择分区,该表达式对要插入到表的行中列值操作;
  • KEY分区:类似HASH,但是HASH允许使用用户自定义表达式,而KEY分区不允许,它需要使用MySQL服务器提供的HASH函数,同时HASH分区只支持整数分区,而KEY分区支持除BLOB和TEXT类型外其他列

创建分区语句

十八、Redis

1.redis 是什么?都有哪些使用场景

Redis是一个开源的,使用ANSI C语言编写,支持网络,可基于内存,可持久化的日志型,key-value数据库

  • 数据高并发的读写
  • 海量数据的读写
  • 对扩展性要求高的数据

2.redis 有哪些功能?

  • 数据缓存功能
  • 分布式锁的功能
  • 支持数据持久化
  • 支持事务
  • 支持消息队列

3.redis 和 memcache 有什么区别?

  • memcache所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型
  • redis的速度比memcache快很多
  • redis可以持久化其数据

4.redis 为什么是单线程的?

因为 cpu 不是 Redis 的瓶颈,Redis 的瓶颈最有可能是机器内存或者网络带宽。既然单线程容易实现,而且 cpu 又不会成为瓶颈,那就顺理成章地采用单线程的方案了。

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

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

5.什么是缓存穿透?怎么解决?

缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。

解决方案:最简单粗暴的方法如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们就把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

6.redis 支持的数据类型有哪些?

  • String、List、Hash、Set、ZSet

7.redis 支持的 java 客户端都有哪些?

Redisson、Jedis、lettuce等等,官方推荐使用Redisson。

8.jedis 和 redisson 有哪些区别?

Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持。

Redisson实现了分布式和可扩展的Java数据结构,和Jedis相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等Redis特性。Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。

9.怎么保证缓存和数据库数据的一致性?

合理设置缓存的过期时间。

新增、更改、删除数据库操作时同步更新 Redis,可以使用事物机制来保证数据的一致性。

10.redis 持久化有几种方式?

  • RDB(Redis Database):指定的时间间隔能对你的数据进行快照存储。
  • AOF(Append Only File):每一个收到的写命令都通过write函数追加到文件中。

11.redis 怎么实现分布式锁?

Redis 分布式锁其实就是在系统里面占一个“坑”,其他程序也要占“坑”的时候,占用成功了就可以继续执行,失败了就只能放弃或稍后重试。

占坑一般使用 setnx(set if not exists)指令,只允许被一个程序占有,使用完调用 del 释放锁。

12.redis 分布式锁有什么缺陷?

Redis 分布式锁不能解决超时的问题,分布式锁有一个超时时间,程序的执行如果超出了锁的超时时间就会出现问题。

13.redis 如何做内存优化?

尽可能使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面。

比如你的web系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的key,而是应该把这个用户的所有信息存储到一张散列表里面。

14.redis 淘汰策略有哪些?

  • volatile-lru:从已设置过期时间的数据集(server. db[i]. expires)中挑选最近最少使用的数据淘汰。
  • volatile-ttl:从已设置过期时间的数据集(server. db[i]. expires)中挑选将要过期的数据淘汰。
  • volatile-random:从已设置过期时间的数据集(server. db[i]. expires)中任意选择数据淘汰。
  • allkeys-lru:从数据集(server. db[i]. dict)中挑选最近最少使用的数据淘汰。
  • allkeys-random:从数据集(server. db[i]. dict)中任意选择数据淘汰。
  • no-enviction(驱逐):禁止驱逐数据。

15.redis 常见的性能问题有哪些?该如何解决?

主服务器写内存快照,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以主服务器最好不要写内存快照。
Redis 主从复制的性能问题,为了主从复制的速度和连接的稳定性,主从库最好在同一个局域网内。

十九、JVM

1.说一下 jvm 的主要组成部分?及其作用?

  • 类加载器(ClassLoader)
  • 运行时数据区(Runtime Data Area)
  • 执行引擎(Execution Engine)
  • 本地库接口(Native Interface)

组件的作用: 首先通过类加载器(ClassLoader)会把 Java 代码转换成字节码,运行时数据区(Runtime Data Area)再把字节码加载到内存中,而字节码文件只是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行,而这个过程中需要调用其他语言的本地库接口(Native Interface)来实现整个程序的功能。

2.说一下 jvm 运行时数据区域?

  • 程序计数器
  • 虚拟机栈
  • 本地方法栈
  • 堆(创建的对象)
  • 方法区(类的属性、成员变量、构造函数等)

有的区域随着虚拟机进程的启动而存在,有的区域则依赖用户进程的启动和结束而创建和销毁。

3.说一下堆栈的区别?

  • 栈内存存储的是局部变量;堆内存存储的是实体;
  • 栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;
  • 栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。

4.队列和栈是什么?有什么区别?

  • 队列和栈都是被用来预存储数据的。
  • 队列允许先进先出检索元素。但也有例外的情况,Deque 接口允许从两端检索元素。
  • 栈和队列很相似,但它对元素进行后进先出的检索。

5.什么是双亲委派模型?

对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立在 JVM 中的唯一性,每一个类加载器,都有一个独立的类名称空间。类加载器就是根据指定全限定名称将 class 文件加载到 JVM 内存,然后再转化为 class 对象。

双亲委派模型:如果一个类加载器收到了类加载的请求,它首先不会自己去加载这个类,而是把这个请求委派给父类加载器去完成,每一层的类加载器都是如此,这样所有的加载请求都会被传送到顶层的启动类加载器中,只有当父加载无法完成加载请求(它的搜索范围中没找到所需的类)时,子加载器才会尝试去加载类。

6.说一下类加载的执行过程?

  1. 加载:根据查找路径找到相应的 class 文件然后导入;
  2. 检查:检查加载的 class 文件的正确性;
  3. 准备:给类中的静态变量分配内存空间;
  4. 解析:虚拟机将常量池中的符号引用替换成直接引用的过程。符号引用就理解为一个标识,而在直接引用直接指向内存中的地址;
  5. 初始化:对静态变量和静态代码块执行初始化工作。

7.怎么判断对象是否可以被回收?

  • 引用计数器:为每个对象创建一个引用计数,有对象引用时计数器 +1,引用被释放时计数 -1,当计数器为 0 时就可以被回收。它有一个缺点不能解决循环引用的问题;
  • 可达性分析:从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是可以被回收的。

8.java 中都有哪些引用类型?

  • 强引用
           默认的引用类型。只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足时,JVM也会直接抛出OutOfMemoryError,不会去回收。如果想中断强引用与对象之间的联系,可以显示的将强引用赋值为null。
  • 软引用
           软引用是用来描述一些非必需但仍有用的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。这种特性常常被用来实现缓存技术,比如网页缓存,图片缓存等。
  • 弱引用
           弱引用的引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收。
  • 虚引用(幽灵引用/幻影引用)
           虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,它随时可能会被回收

9.说一下 jvm 有哪些垃圾回收算法?

  • 标记-清除算法:只回收,不整理
  • 标记-整理算法:标记-清楚算法的优化,解决了内存碎片的问题
  • 复制算法:解决内存碎片
  • 分代回收算法(常用):年轻代以复制为主,老年代以标记-整理为主

10.说一下 jvm 有哪些垃圾回收器?

  • Serial:最早的单线程串行垃圾回收器,新生代垃圾回收器,使用复制算法。
  • Serial Old:Serial 垃圾回收器的老年版本,同样也是单线程的,可以作为 CMS 垃圾回收器的备选预案,老年代垃圾回收器,使用标记-整理算法。
  • ParNew:是 Serial 的多线程版本,新生代垃圾回收器,使用复制算法。
  • Parallel 和 ParNew 收集器类似是多线程的,但 Parallel 吞吐量优先,可以牺牲等待时间换取系统的吞吐量,新生代垃圾回收器,使用复制算法。
  • Parallel Old 是 Parallel 老年版本,Parallel 使用的是复制算法,Parallel Old 使用的是标记-整理的内存回收算法,是老年代垃圾回收器。
  • CMS:一种以获得最短停顿时间为目标的收集器,非常适用 B/S 系统,老年代垃圾回收器,使用标记-清除算法。
  • G1:一种兼顾吞吐量和停顿时间的 GC 实现,是 JDK 9 以后的默认 GC 选项,是整堆回收器,使用标记-整理算法。
垃圾回收器使用算法线程支持新生代/老年代
Serial复制单线程新生代
Serial Old标记-整理单线程老年代
ParNew复制多线程新生代
Parallel Scavenge复制多线程新生代
Parallel Old标记-整理多线程老年代
CMS标记-清除多线程老年代
G1标记-整理多线程整堆

11.详细介绍一下 CMS 垃圾回收器?

CMS(Concurrent Mark-Sweep),是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器。对于要求服务器响应速度的应用上,这种垃圾回收器非常适合。在启动 JVM 的参数加上“-XX:+UseConcMarkSweepGC”来指定使用 CMS 垃圾回收器。

CMS 使用的是标记-清除算法,所以在 gc 的时候会产生大量的内存碎片,当剩余内存不能满足程序运行要求时,系统将会出现 Concurrent Mode Failure,临时 CMS 会采用 Serial Old 回收器进行垃圾清除,此时的性能将会被降低。

12.新生代垃圾回收器和老年代垃圾回收器都有哪些?有什么区别?

新生代回收器:Serial、ParNew、Parallel Scavenge
老年代回收器:Serial Old、Parallel Old、CMS
整堆回收器:G1

新生代垃圾回收器一般采用的是复制算法。复制算法的优点是效率高,缺点是内存利用率低;

老年代垃圾回收器一般采用的是标记-整理算法

13.简述分代垃圾回收器是怎么工作的?

分代回收器有两个分区:老生代和新生代。

新生代的默认空间是 1/3,老生代的默认占比是 2/3。

新生代使用的是复制算法,新生代里有 3 个分区:Eden、To Survivor、From Survivor,它们的默认占比是 8:1:1,它的执行流程如下:

把 Eden + From Survivor 存活的对象放入 To Survivor 区;
清空 Eden 和 From Survivor 分区;
From Survivor 和 To Survivor 分区交换,From Survivor 变 To Survivor,To Survivor 变 From Survivor。

每次在 From Survivor 到 To Survivor 移动时都存活的对象,年龄就 +1,当年龄到达 15(默认配置是 15)时,升级为老生代。大对象也会直接进入老生代。

老生代当空间占用到达某个值之后就会触发全局垃圾收回,一般使用标记整理的执行算法。以上这些循环往复就构成了整个分代垃圾回收的整体执行流程。

14.说一下 jvm 调优的工具?

JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具。

  • jconsole:用于对 JVM 中的内存、线程和类等进行监控;
  • jvisualvm:JDK 自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等。

15.常用的 jvm 调优的参数都有哪些?

  • -Xms2g:初始化堆大小为 2g;
  • -Xmx2g:堆最大内存为 2g;
  • -XX:NewRatio=4:设置年轻代和老年代的内存比例为 1:4;
  • -XX:SurvivorRatio=8:设置新生代 Eden 和 Survivor 比例为 8:2;
  • –XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器组合;
  • -XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器组合;
  • -XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器组合;
  • -XX:+PrintGC:开启打印 gc 信息;
  • -XX:+PrintGCDetails:打印 gc 详细信息。

16.内存溢出、内存泄露、GC的基本概念

内存溢出:out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

内存泄露:memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。其实说白了就是该内存空间使用完毕之后未回收。

gc分为full gc 跟 minor gc(Young GC也就是Minor GC),当每一块区满的时候都会引发gc。

二十、题外话

1.你做过曾经最好的一个东西是什么

因人而异。

2.上一家公司为什么要离职

很简单,个人发展遇到瓶颈,需要突破自己。

3.你还有什么想问的吗

  • 加班要求,(调休/加班费)
  • 薪资情况(税前/税后;薪资结构;多少薪;试用期薪资;报税基数)
  • 时间周期(1年/3年,试用期多久?是否是第三方合同(劳务派遣性质))
  • 福利情况(五险一金,缴纳基数,节假日福利)

写在最后:

        以上题目仅作为参考!想要短时间内突击面试的同学,这里提供更多资料供大家学习和查漏补缺,更有面试技巧分享和简历模板供小伙伴们免费领取。

获取更多面试资料点击这里

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐