vue如何sleep_Java常见面试题 非常实用【个人经验】

本文是一篇关于Java面试的综合整理,涵盖了Java集合、多线程、HashMap与HashTable的区别、线程池、MyBatis、数据库、Redis、RabbitMQ以及JVM等多个方面的知识点。重点讨论了Vue的data双向绑定原理,同时深入讲解了JVM的运行时数据区、垃圾回收机制以及JVM调优。文章旨在帮助读者巩固和准备Java相关面试,特别适合复习和学习。
摘要由CSDN通过智能技术生成

必收藏的Java面试题

目录

Java 面试题

????一.容器部分

????二.多线程部分

????九.其他面试部分

自述

本人正在努力复习,总结面试经验并记录 Java 面试常见问题,欢迎留言监督

一直在更新

容器部分面试题

Java 容器都有哪些

Collection 的子类 List、Set

List 的子类 ArrayList、LinkedList等

Set 的子类 HashSet、TreeSet等

Map 的子类 HashMap、TreeMao等

Collecion 和 Collections 有什么区别

java.util,Collection 是一个集合的顶级接口,它提供了对集合对象进行基本操作的通用接口方法,Collection 接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口的有 List 和 Set

java.util.Collections 是一个包装类(工具类),它包含了各种有关集合操作的静态多态方法。此类不能被实例化,用于对集合中元素进行排序、搜索以及线程安全等各种操作,服务于 Java 的 Collection 框架

List、Set、Map 之间的区别

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

List 是一个有序集合,元素可重复,可有多个NULL值。可以使用各种循环遍历集合,因为它是有序的

Set 是一个无序集合,元素不可重复,重复元素会被覆盖掉(注意:元素虽然无放入顺序,但元素在 Set 中的位置是由该元素的 HashCode 决定的,其位置是固定的,加入 Set 的 Object 必须定义 equals()方法),Set 只能用迭代,因为它是无序的

Map 是由一系列键值对组成的集合,提供了 key 和 value 的映射。在 Map 中保证 key 与 value 一一对应的关系。一个 key 对应一个 value ,不能存在相同的 key,但 value 可以相同

Set 与 List 相比较

Set 检索元素效率较低,删除和插入效率高,因为删除和插入不会引起元素的位置变化

List 可动态增长,查找元素效率高,但是删除和插入效率低,因为删除或插入一条元素,会引起其他元素位置变化

Map 适合存储键值对的数据

HashMap 和 HashTable 的区别

继承的父类不同,但二者都实现了 Map接口

HashTable 继承自 Dictionary 类

HashMap 继承自 AbstractMap 类

线程安全不同

HashMap 在缺省的情况下是非Synchronize的

HashTable 的方法是Synchronize的

在多线程下直接使用 HashTable 不需要自己为它的方法实现同步。但使用 HashMap 时需要手动增加同步处理Map m = Collections.synchronizeMap(hashMap);

是否提供 contains() 方法

HashMap 把 HashTable 的 contains() 方法去掉了,改成了 containsValue() 和 containsKey(),因为 contains 容易让人误解

HashTable 则保留了 contains()、containsValue()、containsKey() 三个方法,其中 contains() 与 containsValue() 功能相同

key 和 value 是否可以为 null 值

HashTable 中,key 和 value 都不能为 null 值

HashMap 中,null 作为键,但这样的键只有一个。可以有多个 value 为 null 值的键。当 get() 方式返回 null 有可能是 HashMap 中没有该键,也有可能返回的 value 为 null。所以 HashMap 用containsKey()方法判断是否存在键

遍历方式不同

HashTable 与 HashMap 都是使用 Iterator 迭代器遍历,而由于历史的原因,HashTable 还使用了 Enumeration 的方式

hash 值不同

哈希值的使用不同,HashTable直接使用对象的HashCode,而 HashMap 重新计算哈希值

hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值

HashTable 使用的取模运算

HashMap 使用的与运算,先用 hash & 0x7FFFFFFF 后,再对 length 取模,&0x7FFFFFFF 的目的是为了将负的 hash 值转化为正值,因为 hash 值有可能为负数,而 &0x7FFFFFFF 后,只有符号外改变,而后面的位都不变

内部实现使用的数组初始化和扩容方式不同

HashTable 在不指定容量的情况下默认是11,而 HashMap 为16,HashTable 不要求底层数组的容量一定要是2的整数次幂,而 HashMap 底层数组则一定为2的整数次幂

HashTable 扩容时,将容量变成原来的2倍+1 (old * 2 + 1),而 HashMap 则直接改为原来的2倍 (old * 2)

如何决定使用 HashMap 还是 TreeMap

如果需要得到一个有序的 Map 集合就应该使用 TreeMap (因为 HashMap 的排序顺序不是固定的)除此之外,由于 HashMap 有比 TreeMap 更好的性能,在不需要使用排序的情况下使用 HashMap 会更好

HashMap 的实现原理

利用key的hashCode重新hash计算出当前对象的元素在数组中的下标

存储时,如果出现hash值相同的key,此时有两种情况。(1)如果key相同,则覆盖原始值;(2)如果key不同(出现冲突),则将当前的key-value放入链表中

获取时,直接找到hash值对应的下标,在进一步判断key是否相同,从而找到对应值。

理解了以上过程就不难明白HashMap是如何解决hash冲突的问题,核心就是使用了数组的存储方式,然后将冲突的key的对象放入链表中,一旦发现冲突就在链表中做进一步的对比。

HashSet 的实现原理

HashSet 实际上是一个 HashMap 实例,都是一个存放链表的数组。它不保证存储元素的迭代顺序;此类允许使用 null 元素。HashSet 中不允许有重复元素,这是因为 HashSet 是基于 HashMap 实现的,HashSet 中的元素都存放在 HashMap 的 key 上面,而 value 中的值都是统一的一个固定对象 private static final Object PRESENT = new Object();

HashSet 中 add() 方法调用的是底层 HashMap 中的 put() 方法,而如果是在 HashMap 中调用 put() ,首先会判断 key 是否存在,如果 key 存在则修改 value 值,如果 key 不存在这插入这个 key-value。而在 set 中,因为 value 值没有用,也就不存在修改 value 值的说法,因此往 HashSet 中添加元素,首先判断元素(也就是key)是否存在,如果不存在这插入,如果存在着不插入,这样 HashSet 中就不存在重复值。所以判断 key 是否存在就要重写元素的类的 equals() 和 hashCode() 方法,当向 Set 中添加对象时,首先调用此对象所在类的 hashCode() 方法,计算次对象的哈希值,此哈希值决定了此对象在Set中存放的位置;若此位置没有被存储对象则直接存储,若已有对象则通过对象所在类的 equals() 比较两个对象是否相同,相同则不能被添加。

ArrayList 与 LinkList 的区别是什么

AarrayList 是动态数组构成 LinkList 是链表组成

AarrayList 常用于经常查询的集合,因为 LinkList 是线性存储方式,需要移动指针从前往后查找

LinkList 常用于新增和删除的集合,因为 ArrayList 是数组构成,删除某个值会对下标影响,需要进行数据的移动

AarrayList 自由度较低,需要手动设置固定的大小,但是它的操作比较方便的,①直接创建②添加对象③根据下标进行使用

LinkList 自由度较高,能够动态的随数组的数据量而变化

ArrayList 主要开销在List需要预留一定空间

LinkList 主要开销在需要存储结点信息以及结点指针信息

如何实现数组与 List 之间的转换

List to Array : 可以使用 List 的 toArray() 方法,传入一个数组的类型例如 Stirng[] strs = strList.toArray(new String[strList.size()]);

Array to List : 可以使用 java.util.Arrays 的 asList()方法 例如 List strList = Arrays.asList(strs);

ArrayList 与 Vector 的区别是什么

ArrayList 是非线程安全的,而 Vector 使用了 Synchronized 来实现线程同步的

ArrayList 在性能方面要优于 Vector

ArrayList 和 Vector 都会根据实际情况来动态扩容的,不同的是 ArrayList 扩容到原大小的1.5倍,而 Vector 扩容到原大小的2倍

Array 与 ArrayList 有什么区别

Array 是数组,当定义数组时,必须指定数据类型及数组长度

ArrayList 是动态数组,长度可以动态改变,会自动扩容,不使用泛型的时候,可以添加不同类型元素

在 Queue 中 poll() 与 remove() 有什么区别

poll() 和 remove() 都是从队列头删除一个元素,如果队列元素为空,remove() 方法会抛出NoSuchElementException异常,而 poll() 方法只会返回 null

哪些集合类是线程安全的

Vector :比 ArrayList 多了同步化机制(线程安全)

HashTable :比 HashMap 多了线程安全

ConcurrentHashMap :是一种高效但是线程安全的集合

Stack :栈,继承于 Vector 也是线程安全

迭代器 Iterator 是什么

Iterator 是集合专用的遍历方式

Iterator iterator() : 返回此集合中元素的迭代器,通过集合的iterator()方法得到,所以Iterator是依赖于集合而存在的

Iterator 怎么使用 ? 有什么特点

Iterator 的使用方法

java.lang.Iterable 接口被 java.util.Collection 接口继承,java.util.Collection 接口的 iterator() 方法返回一个 Iterator 对象

next() 方法获取集合中下一个元素

hasNext() 方法检查集合中是否还有元素

remove() 方法将迭代器新返回的元素删除

Iterator 的特点

Iterator 遍历集合过程中不允许线程对集合元素进行修改

Iterator 遍历集合过程中可以用remove()方法来移除元素,移除的元素是上一次Iterator.next()返回的元素

Iterator 的next()方法是通过游标指向的形式返回Iterator下一个元素

Iterator 与 LinkIterator 有什么区别

使用范围不同

Iterator 适用于所有集合, Set、List、Map以及这些集合的子类型,而 ListIterator 只适用于 List 及其子类型

ListIterator 有 add() 方法,可以向 List 中添加元素,而 Iterator 不能

ListIterator 和 Iterator 都有 hasNext() 和 next() 方法,来实现顺序向后遍历。而 ListIterator 有 hasPrevious() 和 previous() 方法,可以实现逆向遍历,但是 Iterator 不能

ListIterator 可以使用 nextIdnex() 和 previousIndex() 方法定位到当前索引位置,而 Iterator 不能

它们都可以实现 remove() 删除操作,但是 ListIterator 可以使用 set() 方法实现对象修改,而 Iterator 不能

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

可以采用 java.util.Collections 工具类

Collections.unmodifiableMap(map)

Collections.unmodifiableList(list)

Collections.unmodifiableSet(set)

如诺修改则会报错java.lang.UnsupportedOperationException

多线程部分面试题

并发和并行有什么区别

并发:不同的代码块交替执行

并行:不同的代码块同时执行

个人理解

并发就是放下手头的任务A去执行另外一个任务B,执行完任务B后,再回来执行任务A,就比如说吃饭时来电话了,去接电话,打完电话后又回来吃饭

并行就是执行A的同时,接受到任务B,然后我一起执行,就比如说吃饭时来电话了,一边吃饭一边打电话

线程和进程的区别

根本区别 :进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位

在操作系统中能同时运行多个进程,进程中会执行多个线程

线程是操作系统能够进行运算调度的最小单位

守护线程是什么

JVM内部的实现是如果运行的程序只剩下守护线程的话,程序将终止运行,直接结束。所以守护线程是作为辅助线程存在的

创建线程有哪几种方式

继承Thread类创建线程类

定义Thread类的子类,并重写该类的run()方法

创建Thread子类的实例,即创建了线程对象

调用线程对象的start()方法来启动该线程

实现Runnable接口创建线程类

创建runnable接口的实现类,并重写该接口的run()方法

创建Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该 Thread对象才是真正的线程对象

调用线程对象的start()方法来启动该线程

通过 Callable 和 Future 创建线程

创建Callable接口的实现类,并重写call()方法,该call()方法将作为线程执行体,并且有返回值

创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值

使用FutureTask对象作为Thread对象的target创建并启动新线程

调用FutureTask对象的get()方法来获得子线程执行结束后的返回值

runnable 和 callable 有什么区别

相同点

都是接口

都可以编写多线程程序

都是采用Thread.start()启动线程

不同点

Runnable没有返回值,Callable可以返回执行结果,是个泛型和Future、FutureTask配合可以用来获取异步执行的结果

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

注意 Callalble接口支持返回执行结果,需要调用FutureTask.get()得到,此方法会阻塞主进程的继续往下执行,如果不调用不会阻塞

线程有哪些状态

新建 就绪 运行 阻塞 死亡

sleep() 和 wait() 的区别

最大区别是sleep() 休眠时不释放同步对象锁,其他线程无法访问 而wait()休眠时,释放同步对象锁其他线程可以访问

sleep() 执行完后会自动恢复运行不需要其他线程唤起.而 wait() 执行后会放弃对象的使用权,其他线程可以访问到,需要其他线程调用 Monitor.Pulse() 或者 Monitor.PulseAll() 来唤醒或者通知等待队列

线程的 run() 和 start() 的区别

start() 是来启动线程的

run() 只是 Thread 类中一个普通方法,还是在主线程中执行

notify() 和 notifyAll() 有什么区别

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

notifyAll() 唤醒对象的等待池中的所有线程,进入锁池。

创建线程池有哪几种方式

利用Executors创建线程池

newCachedThreadPool(),它是用来处理大量短时间工作任务的线程池

newFixedThreadPool(int nThreads),重用指定数目nThreads的线程

newSingleThreadExecutor(),它的特点在于工作线程数目限制为1

newSingleThreadScheduledExecutor()和newScheduledThreadPool(int corePoolSize),创建的是个ScheduledExecutorService,可以进行定时或周期性的工作调度,区别在于单一工作线程还是多个工作线程。

newWorkStealingPool(int parallelism),这是一个经常被人忽略的线程池,Java 8 才加入这个创建方法,其内部会构建ForkJoinPool,利用Work-Stealing算法,并行地处理任务,不保证处理顺序

线程池都有哪些状态

运行 RUNNING:线程池一旦被创建,就处于 RUNNING 状态,任务数为 0,能够接收新任务,对已排队的任务进行处理

关闭 SHUTDOWN:不接收新任务,但能处理已排队的任务。调用线程池的 shutdown() 方法,线程池由 RUNNING 转变为 SHUTDOWN 状态

停止 STOP:不接收新任务,不处理已排队的任务,并且会中断正在处理的任务。调用线程池的 shutdownNow() 方法,线程池由(RUNNING 或 SHUTDOWN ) 转变为 STOP 状态

整理 TIDYING:

SHUTDOWN状态下,任务数为 0, 其他所有任务已终止,线程池会变为 TIDYING 状态,会执行 terminated() 方法。线程池中的 terminated() 方法是空实现,可以重写该方法进行相应的处理

线程池在 SHUTDOWN 状态,任务队列为空且执行中任务为空,线程池就会由 SHUTDOWN 转变为 TIDYING 状态

线程池在 STOP 状态,线程池中执行中任务为空时,就会由 STOP 转变为 TIDYING 状态

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

线程池中的 submit() 和 execute() 有什么区别

两个方法都可以向线程池提交任务

execute()方法的返回类型是 void,它定义在Executor接口中

而submit()方法可以返回持有计算结果的 Future 对象,它定义在ExecutorService接口中

在Java程序中怎么确保多线程运行安全

使用synchronied关键字

使用volatile 关键字,防止指令重排,所有对该变量读写都是直接操作共享内存

lock锁机制 lock()与unlock()

使用线程安全的类 比如StringBuffer、HashTable、Vector等

线程安全问题主要是:原子性,可见性,有序性

synchronized 和 volatile 的作用什么?有什么区别

作用

synchronized 表示只有一个线程可以获取作用对象的锁,执行代码,阻塞其他线程

volatile 表示变量在 CPU 的寄存器中是不确定的,必须从主存中读取。保证多线程环境下变量的可见性,禁止指令重排序

区别

synchronized 可以作用于变量、方法、对象。volatile 只能作用于变量

synchronized 可以保证线程间的有序性、原子性和可见性。volatile 只保证了可见性和有序性,无法保证原子性

synchronized 线程阻塞,volatile 线程不阻塞

synchronized 和 Lock 有什么区别

synchronized是一个Java关键字,在jvm层面上,而Lock是一个类

synchronized以获取锁的线程执行完同步代码,释放锁,如果线程中发生异常,jvm会让线程释放锁。而Lock必须在finally中释放锁,否则容易造成线程死锁

Lock可以查看锁的状态,而synchronized不能

在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择

synchronized是非公平锁,而Lock是可公平锁

Spring Mvc面试题部分

为什么要是使用 Spring

轻量 非侵入型框架

控制反转 IOC,促进了松耦合

面向切面编程 AOP

容器 采用Java Bean 代替 沉重的EJB容器

方便集成 可以和很多框架相互集成如Mybatis、Shiro

丰富的功能 Spring 已经写好了很多常的模板如JDBC抽象类、事务管理、JMS、JMX、Web Service...等

解释一下什么是 aop

AOP是面向切面编程,是OOP编程的有效补充

AOP包括Aspect切面,Join Point连接点,Advice通知,Ponitcut切点

其中Advice通知包括5中模式

Before advice:方法执行前‘增强’

After returning advice:方法执行后‘增强’

After throwing advice:方法执行中抛出异常时‘增强’

After finally advice:方法执行完后‘增强’

Around advice:环绕增强‘以上四种的整合’

解释一下什么是 ioc

IOC是控制反转,是将代码本身的控制权移到外部Spring容器中进行集中管理,也是为了达到松耦合

Spring 主要有哪些模块

Spring Core

框架基础部分,提供了IOC容器,对Bean进行集中管理

Spring Context

基于Bean,提供上下文信息

Spring Dao

提供了JDBC的抽象层,它可消除冗长的JDBC编码,提供了声明性事务管理方法

Spring ORM

提供了对象/关系映射常用的API集成层,如Mybatis、Hibernate等

Spring Aop

提供了AOP面向切面的编程实现

Spring Web

提供了Web开发的信息上下文,可与其他的Web集成开发

Spring Web Mvc

提供了Web应用的Model - View - Controller全功能的实现

Spring 常用的注入方式有哪些

构造方法注入

Setter方法注入

不过值得一提的是:Setter注入时如果写了带参构造方法,那么无参构造方法必须也要写上,否则注入失败

基于注解得注入

基本上有五种常用注册Bean的注解

@Component:通用注解

@Controller:注册控制层Bean

@Service:注册服务层Bean

@Repository:注册Dao层Bean

@Configuration:注册配置类

Spring 中的 bean 是线程安全的吗

线程不安全

Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性

Spring 支持几种 bean 的作用域

singleton:单例,默认的作用域

prototype:原型,每次都会创建新对象

request:请求,每次Http请求都会创建一个新对象

session:会话,同一个会话创建一个实例,不同会话使用不同实例

global-session:全局会话,所有会话共享一个实例

后面三种只有在Web应用中使用Spring才有效

Spring 自动装配 bean 有哪些方式

default:默认方式和‘no’效果一样

no:不自动配置,需要使用 节点或参数

byName:根据名称进行装配

byType:根据类型进行装配

constructor:根据构造函数进行装配

Spring 事务实现方式有哪些

编程式事务管理对基于 POJO 的应用来说是唯一选择,我们需要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理

基于 TransactionProxyFactoryBean的声明式事务管理

基于 @Transactional 的声明式事务管理

基于Aspectj AOP配置事务

Spring 的事务隔离是什么

Spring Mvc 的运行流程

用户发送一个请求至前端控制器DispatcherServlet

DispatcherServlet收到请求调用处理器映射器HandlerMapping

处理器映射器根据请求url找到具体的处理器,生成处理器执行链HandlerExecutionChain(包括处理器对象和处理器拦截器)一并返回给DispatcherServlet

DispatcherServlet根据处理器Handler获取处理器适配器HandlerAdapter执行HandlerAdapter处理一系列的操作

执行处理器Handler(Controller,也叫页面控制器)

Handler执行完成返回ModelAndView到HandlerAdapter

HandlerAdapter将Handler执行结果ModelAndView返回到DispatcherServlet

DispatcherServlet``将ModelAndView传给ViewReslover视图解析器

ViewReslover解析后返回具体View

DispatcherServlet对View进行渲染视图(即将模型数据model填充至视图中)

DispatcherServlet响应用户

Spring Mvc 有哪些组件

DispatcherServlet:前端控制器

HandlerMapping:处理器映射器

HandlerAdapter:处理器适配器

HandlerInterceptor:拦截器

ViewResolver:视图解析器

MultipartResolver:文件上传处理器

HandlerExceptionResolver:异常处理器

DataBinder:数据转换

HttpMessageConverter:消息转换器

FlashMapManager:页面跳转参数管理器

HandlerExecutionChain:处理程序执行链

RequestToViewNameTranslator:请求转视图翻译器

ThemeResolver:

LocaleResolver:语言环境处理器

@RequestMapping 的作用是什么

@RequestMapping是一个注解,用来标识 http 请求地址与 Controller 类的方法之间的映射

指定 http 请求的类型使用

GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE

@Autowired 与 @Resource 的区别

@Autowired为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired,采取的策略为按照类型注入

@Resource注解由J2EE提供,需要导入包javax.annotation.Resource,默认按照ByName自动注入

Mybatis部分面试题

Mybatis 中 #{} 和 ${} 的区别

#{} 表示一个占位符

可以有效的防止SQL注入

${} 表示拼接SQL串

可以用于动态判断字段

order by ${field} desc可以动态修改fieId来达到动态根据字段降序查询

Mybatis 有几种分页方式

原始分割

取出数据后,进行手动分割

LIMIT关键字

修改执行SQL语句

RowBounds实现分页

将PageInfo信息封装成RowBounds,调用DAO层方法

Mybatis的Interceptor实现

原理就是执行SQL语句前,在原SQL语句后加上limit关键字,不用自己去手动添加

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

RowBounds 表面是在“所有”数据中检索数据,其实并非是一次性查询出所有数据,因为 MyBatis 是对 jdbc 的封装,在 jdbc 驱动中有一个 Fetch Size 的配置,它规定了每次最多从数据库查询多少条数据,假如你要查询更多数据,它会在你执行 next()的时候,去查询更多的数据。就好比你去自动取款机取 10000 元,但取款机每次最多能取 2500 元,所以你要取 4 次才能把钱取完。只是对于 jdbc 来说,当你调用 next()的时候会自动帮你完成查询工作。这样做的好处可以有效的防止内存溢出。

Mybatis 逻辑分页和物理分页的区别是什么

逻辑分页是一次性查询很多数据,然后再在结果中检索分页的数据。这样做弊端是需要消耗大量的内存、有内存溢出的风险、对数据库压力较大。

物理分页是从数据库查询指定条数的数据,弥补了一次性全部查出的所有数据的种种缺点,比如需要大量的内存,对数据库查询压力较大等问题

Myabtis 是否支持延迟加载,延迟加载的原理是什么

MyBatis 支持延迟加载,设置 lazyLoadingEnabled=true 即可

延迟加载的原理的是调用的时候触发加载,而不是在初始化的时候就加载信息。比如调用 a.getB().getName(),这个时候发现 a.getB() 的值为 null,此时会单独触发事先保存好的关联 B 对象的 SQL,先查询出来 B,然后再调用 a.setB(b),而这时候再调用 a.getB(). getName() 就有值了,这就是延迟加载的基本原理

Mybatis 一级缓存和二级缓存

一级缓存

基于PerpetualCache的 HashMap本地缓存,它的声明周期是和 SQLSession一致的,有多个 SQLSession 或者分布式的环境中数据库操作,可能会出现脏数据

当Session flush或close 之后,该Sessio中的所有Cache 就将清空,默认一级缓存是开启的

二级缓存

也是基于PerpetualCache的 HashMap本地缓存,不同在于其存储作用域为Mapper 级别的,如果多个SQLSession之间需要共享缓存,则需要使用到二级缓存

二级缓存可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现 Serializable 序列化接口(可用来保存对象的状态)

扩展

开启二级缓存后的查询流程:二级缓存 -> 一级缓存 -> 数据库

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

Mybatis 和 Hibernate 有哪些区别

Mybatis 更加灵活,可以自己写SQL语句

也正是自己写了很多SQL语句,所以移植性比较差

Mybatis 入门比较简单,使用门槛也低

hibernate 可以自行把二级缓存更换为第三方的

Mybatis 有哪些执行器

SimpleExecutor:每执行一次UPDATE\SELECT 就开启一个Statement对象,用完后立即关闭

ReuseExecutor:执行 UPDATE\SELECT,以 SQL 作为 key 查找Statement对象,存在就使用,不存在就创建,用完后不关闭Statement对象,而是放置于 Map 内供下一次使用。简言之,就是重复使用Statement`对象

BatchExecutor:执行 UPDATE(没有 select,jdbc 批处理不支持 select),将所有 SQL 都添加到批处理中addBatch(),等待统一执行executeBatch(),它缓存了多个 Statement 对象,每个 Statement 对象都是 addBatch() 完毕后,等待逐一执行 executeBatch() 批处理,与 jdbc 批处理相同

Mybatis 分页插件的实现原理是什么

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

Mybatis 如何编写一个自定义插件

MyBatis 自定义插件针对 MyBatis 四大对象(Executor、StatementHandler、ParameterHandler、ResultSetHandler)进行拦截

Executor:拦截内部执行器,它负责调用 StatementHandler 操作数据库,并把结果集通过 ResultSetHandler 进行自动映射,另外它还处理了二级缓存的操作

. StatementHandler:拦截 SQL 语法构建的处理,它是 MyBatis 直接和数据库执行 SQL 脚本的对象,另外它也实现了 MyBatis 的一级缓存

ParameterHandler:拦截参数的处理

ResultSetHandler:拦截结果集的处理

MyBatis 插件要实现 Interceptor 接口

setProperties 方法是在 MyBatis 进行配置插件的时候可以配置自定义相关属性,即:接口实现对象的参数配置

plugin 方法是插件用于封装目标对象的,通过该方法我们可以返回目标对象本身,也可以返回一个它的代理,可以决定是否要进行拦截进而决定要返回一个什么样的目标对象,官方提供了示例:return Plugin. wrap(target, this)

intercept 方法就是要进行拦截的时候要执行的方法

public interface Interceptor {

Object intercept(Invocation invocation) throws Throwable;

Object plugin(Object target);

void setProperties(Properties properties);

}

官方插件实现:

@Intercepts({@Signature(type = Executor. class, method = "query",

args = {MappedStatement. class, Object. class, RowBounds. class, ResultHandler. class})})

public class TestInterceptor implements Interceptor {

public Object intercept(Invocation invocation) throws Throwable {

Object target = invocation. getTarget(); //被代理对象

Method method = invocation. getMethod(); //代理方法

Object[] args = invocation. getArgs(); //方法参数

// do something . . . . . . 方法拦截前执行代码块

Object result = invocation. proceed();

// do something . . . . . . . 方法拦截后执行代码块

return result;

}

public Object plugin(Object target) {

return Plugin. wrap(target, this);

}

}

MySQL部分面试题

数据库的三范式是什么

如何获取当前数据库的版本

说一下 ACID 是什么

char 和 varchar 的区别

float 和 double 的区别

MySQL 内连接、左连接、右连接有什么区别

MySQL 的索引是怎么实现的

怎么验证 MySQL 的索引是否满足需求

数据的事务隔离

MySQL 常用的引擎

InnoDB 和 Myisam 都是用 B+Tree 来存储数据的

InnoDB 支持事务,且支持四种隔离级别(读未提交、读已提交、可重复读、串行化),默认的为可重复读.

Myisam 只支持表锁,且不支持事务.Myisam 由于有单独的索引文件,在读取数据方面的性能很高.

MySQL 的行锁和表锁

乐观锁和悲观锁

MySQL 问题排查都有哪些手段

如何做 MySQL 的性能优化

Redis部分面试题

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

Redis 为什么是单线程的

Redis 的缓存预热

在项目配置文件中生命自定义的key ,在项目启动时会判断redis是否存在key ,如果没有就会创建一个key传入null值

数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中

redis 缓存雪崩是什么,怎么解决 ?

缓存雪崩是指,缓存层出现了错误,不能正常工作了.于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况.

解决方案

redis 高可用 就是搭建 redis 集群,其中一台redis挂掉后 可以使用其他的 redis

限流降级 就是每一个 key 只能一个线程来查询数据和缓存,其他线程等待

数据预热 数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中.在即将发生大并发访问前手动触发加载缓存不同的 key ,设置不同的过期时间,让缓存失效的时间点尽量均匀.*

缓存穿透是什么?如何解决

就是访问redis数据库,查不到数据,就是没有命中,会去持久化数据库查询,还是没有查到.假如高并发的情况下,持久化数据库一下增加了很大压力,就相当于出现了缓存穿透

解决方案

缓存空对象 在存储层命中失败后,即使返回空对象也将其缓存,并设置一个过期时间,之后访问的这个数据将会从缓存中取出,很好的保护了后端数据源,这样也会有出现问题 例如空值被缓存也就会增加大量的缓存空间,设置了过期时间还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响

布隆过滤器 对所有可能查询的参数以 hash 形式存储,查询时发现值不存在就直接丢弃,不会去持久层查询

Redis 支持的数据类型有哪些

Redis 支持的 Java 客户端有哪些

Jedis 与 Redisson 有哪些区别

怎么保证缓存与数据库数据的一致性

Redis 持久化有几种方式

Redis 怎么实现分布式锁

Redis 分布式锁有什么缺陷

Redis 如何做内存优化

Redis 淘汰策略有哪些

Redis 常见的问题有哪些? 该如何解决

RabbitMQ部分面试题

RabbitMq 的使用场景有哪些

RabbitMq 有哪些重要的角色

RabbitMQ的消息存储方式

RabbitMQ 对于 queue 中的 message 的保存方式有两种方式:disc 和 ram.如果采用disc,则需要对 exchange/queue/delivery mode 都要设置成 durable 模式. Disc 方式的好处是当 RabbitMQ 失效了, message 仍然可以在重启之后恢复.而使用 ram 方式, RabbitMQ 处理 message 的效率要高很多, ram 和 disc 两种方式的效率比大概是 3:1.所以如果在有其它 HA 手段保障的情况下,选用 ram 方式是可以提高消息队列的工作效率的.

RabbitMq 中 vhost 的作用是什么

RabbitMq 的消息是怎么发送的

RabbitMq 怎么保证消息的稳定性

RabbitMq 怎么避免丢失消息

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

RabbitMq 持久化有什么缺点

RabbitMq 有几种广播方式

RabbitMq 节点的类型有哪些

RabbitMq 集群搭建需要注意哪些问题

RabbitMq 每个节点是其他节点的完整拷贝吗

RabbitMq 集群中唯一一个磁盘节点崩溃了会发生什么

RabbitMq 对集群停止顺序有要求吗

JVM部分面试题

JVM 主要的组成部分?及其作用

JVM 运行时数据区是什么

堆和栈的区别

栈内存用来存储局部变量和方法调用

而堆内存用来存储 Java 中的对象.无论是成员变量,局部变量,还是类变量.,它们指向的对象都存储在堆内存中.

栈内存归属单个线程,一个栈对应一个线程,其中储存的变量只能在该线程中可以访问到,也可以理解为私有内存

而堆内存中的对象 所有线程均可见,堆内存中对象可以被所有线程访问到

栈内存要远小于堆内存

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

什么是双亲委派模型

类加载的执行过程

怎么判断对象是否可以收回

Java 中有哪些引用类型

JVM 中垃圾回收算法

JVM 有哪些垃圾回收器

介绍一下 CMS 垃圾回收器

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

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

JVM 调优的工具有哪些

JVM 调优的参数有哪些

其他部分面试题

Api 接口如何实现 ?

在类里使用 implements 关键字实现 Api 接口

MySQL 链接数据库常用的几种方式 ?

Mybatis 框架

Hibernate 框架

JDBC 技术

c3p0 连接池

dbcp 连接池

SpringBoot 如何集成 Redis ?

在 pom.xml 文件引入 redis 依赖

org.springframework.boot

spring-boot-starter-data-redis

在 application 配置文件中 书写 redis 配置

spring.redis.host=127.0.0.1

#Redis服务器连接端口

spring.redis.port=6379

#Redis服务器连接密码(默认为空)

#spring.redis.password=

SpringCloud 的优点 ?

服务之间采用Restful等轻量级通讯

精准的制定优化服务方案,提高系统的可维护性

服务之间拆分细致,资源可重复利用,提高开发效率

SpringCloud 用了哪些组件 ?

netflix Eureka 注册中心

netflix Ribbon 负载均衡

netflix Zuul 网关

netflix Hystrix 熔断器

feign 服务调用

List 和 Set 的区别

List 允许有多个重复对象,而 Set 不允许有重复对象

List 允许有多个NULL值,而 Set 只允许有一个NULL值

List 是一个有序的容器,输出顺序即是输入顺序

Set 是一个无序的容器无法保证每个元素的顺序,但是可以用 TreeSet 通过 Comparator 或者 Comparable 维护排序顺序

List的实现类有 ArrayList、LinkList、Vector 其中 ArrayList 最常用于查询较多,随意访问.LinkList 同于新增和删除较多的情况,Vector 表示底层数组,线程安全象

Set的实现类有 HashSet、TreeSet、LinkedHashSet 其中基于 HashMap 实现的 HashSet 最为流行,TreeSet 是一个有序的Set容器象

扩展

Map的实现类有HashMap、HashTable、TreeMap

Java 中 static 的作用

表示全局或静态的意思、用来修饰成员变量和成员方法,也可以形成静态代码块

达到了不用实例化就可以使用被 public static 修饰的变量或方法

什么单例模式 ?

保证整个项目中一个类只有一个对象的实例,实现这种功能就叫做单例模式

单例模式的好处:

单例模式节省公共资源

单例模式方便控制

如何保证是单利模式 ?

构造私有化

以静态方法返回实例

确保对象实例只有一个

单例模式有哪几个 ?

饿汉模式

把对象创建好,需要使用的时候直接拿到就行

懒汉模式

等你需要的时候在创建对象,后边就不会再次创建

SpringBoot 常用的几个注解 ?

@SpringBootApplication SpringBoot的核心注解 启动类

@EnableAutoConfiguration 开启SpringBoot自动配置

@RestController 在控制层 是@ResponseBody注解与@Controller注解的合集

@RequestMapper 处理请求地址映射的注解

@RequestParam 获取url上传过来的参数

@Configuration 声明配置类

@Component 通用注解

@Service 业务逻辑层

Java 八大数据类型

char 字符型 byte 字节型 boolean 布尔型

float 单浮点型 double 双浮点型

int 整数型 short 短整数型 long 长整数型

MySQL分页和升序降序如何实现 ?

可以用 limit

select name,age,sex from t_student limit(0,5);

升序 order by xx asc

select name,age,sex from t_student order by age asc;

降序 order by xx desc

select name,age,sex from t_student order by age desc;

maven 是干什么的,它有什么好处 ?

maven 专门构建和管理Java项目的工具

maven的好处在于可以将项目过程规范化、自动化、高效化以及强大的可扩展性

Sql调优

创建索引 尽量避免全盘扫描 首先考虑在 where 和 order by 涉及的列上创建索引

避免在索引上使用计算 注意就是IN关键字不走索引,它是走全盘扫描

使用预编译防止 sql 注入

尽量将多条 SQL语句压缩到一条 SQL 语句中

最最最好的就是少用 * , 应该写成要查询的字段名,尽量避免在 where 条件中判断 null

尽量不用like 的前置百分比

对于连续的数值,能用 between 就不要用 in

在新建临时表时,如果一次性插入数据量较大.可以用 select into 代替 create table

MySQL 如何添加索引 ?

PRIMARY KEY (主键索引)

添加INDEX(普通索引) ALTER TABLE table_name ADD INDEX index_name ( column )

添加FULLTEXT(全文索引) ALTER TABLE table_name ADD FULLTEXT ( column)

添加多列索引 ALTER TABLE table_name ADD INDEX index_name ( column1, column2, column3 )

MySQL 索引的实现方式?

MySQL 索引底层的实现方式是 B+Tree也就是B+树 具体查看 B+Tree实现方式

Vue的数据双向绑定原理

使用v-mode属性, 它的原理是利用了Object.defineProperty()方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的

ActiveMQ的消息存储方式

采取先进先出模式,同一时间,消息只会发送给某一个消费者,只有当该消息被消费并告知已收到时,它才能在代理的存储中被删除.

对于持久性订阅来说,每一个消费者都会获取消息的拷贝.为了节约空间,代理的存储介质中只存储了一份消息,存储介质的持久订阅对象为其以后的被存储的消息维护了一个指针,消费者消费时,从存储介质中复制一个消息.消息被所有订阅者获取后才能删除.

KahaDB消息存储

基于文件的消息存储机制,为了提高消息存储的可靠性和可恢复性,它整合了一个事务日志.KahaDB拥有高性能和可扩展性等特点.由于KahaDB使用的是基于文件的存储,所以不需要使用第三方数据库

原文:https://www.cnblogs.com/beixuan/p/13381722.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值