吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2558|回复: 8
收起左侧

[Java 转载] JAVA新手面试整理

  [复制链接]
username11 发表于 2021-8-17 16:05

1、JDK、JRE、JVM区别和联系

jvm:java虚拟机。它只认识 xxx.class 这种类型的文件,它能够将 class 文件中的字节码指令进行识别并调用操作系统向上的 API 完成动作。所以说,jvm 是 Java 能够跨平台的核心

jre:运行环境。它主要包含两个部分,jvm 的标准实现和 Java 的一些基本类库。它相对于 jvm 来说,多出来的是一部分的 Java 类库。

jdk:开发工具包。包含jre和jvm。

2、==和equals的区别

==:用于比较引用和比较基本数据类型时具有不同的功能。

equal:用来检测两个对象是否相等,即两个对象的内容是否相等。

3、final

被final修饰的变量不能被改变,被final修饰的类不能被继承,被final修饰的方法不能被重写。

4、String、StringBuffer、StringBuild

String:是一个不可变字符串,底层使用final修饰

  • 在修改字符串操作比较多的时候用StringBuilder或StringBuffer.
  • 在要求线程安全的情况下用StringBuffer
  • 在不要求线程安全的情况下用StringBuilder

5、重载和重写的区别

  • 重载:方法名一致,参数列表不同,参数类型不同。与返回值无关
  • 重写:方法名一致,参数列表一致,返回类型一致,存在子类中。

6、接口和抽象类

  • 抽象类:只能单继承。可以存在普通成员函数。成员变量可以是多种类型的。
  • 接口:多实现。只能只存在public abstract方法。只能是 publi static final类型的。

7、list和set的区别

  • list:有序可重复。按对象进入顺序保存对象,允许多个Null元素对象,可以用iteratiterator遍历取出所有元素。在逐一遍历,还可以使用get(int index)获取指定下标元素。
  • set:无序不可重复最多允许一个Null元素对象,取元素时只能通过iteratoriterator取得所有元素,在逐一遍历各个元素。

8、hashCode和equals

  • 两者都是比较对象
  • equals比较,比较的比较全面、比较复杂,性能低,所以加上hashCode取得hash码更加快速,准确。
  • 直接使用hashCode来比较的话,不同的对象可能会拥有相同的hash码,所以比较的结果不是那么的准确。

9、ArrayList和linkedList区别

  • ArrayList基于数组实现,连续存储在内存中。从中间插入元素比linkedList慢,因为他会将其之后的元素复制,再写入。从末尾添加就不会比linkedList慢~
  • linkedList基于链表实现,分散在内存中。

10、HashMap和HashTable的区别

  • HashMap:非线程安全的,允许key和value为null。
    • 底层基于链表和数组实现。java8开始链表高度达到8,数组长度超过64,链表转化为红黑树,元素以内部类Node节点存在。
    • key为nul,存在下标0的位置。
  • HashTable:线程安全的,每一个方法synchronized修饰。不允许key和value为null

11、ConcurrentHashMap原理,jdk7和jdk8版本的区别

jdk1.7

  • 数据结构:ReentrantLock+Segment+HashEntity,一个Segment中包含一个HashEntity数组,每个HashEntity又是一个链表结构

jdk1.8

  • synchronized+CAS(乐观锁)+Node+红黑树,Node的val和next都用volatile修饰,保证可见性,查找、替换、赋值操作都是使用CAS

12、如何实现一个IOC容器

  • 配置文件配置包扫描路径
  • 递归包扫描获取.class文件
  • 反射、确定需要交给ioc管理的类
  • 对需要注入的类进行依赖注入

13、java类加载器有哪些

  • 根加载器,bootstraClassLoader
  • 扩展加载器:ExtenuationClassLoader
  • 应用程序加载器:AppClassLoader
  • 自定义加载:比如阿里巴巴觉得JDK8不好用,自己编写一个alibbaJDK.(高端定制)

14、什么叫双亲委派机制?

  • 类加载器去加载类的时候,从上往下加载,加载到了类,后边的就不加载了。

双亲委派机制的作用就是保证程序的安全。

15、什么是字节码?

.class文件中的二进制数据就是字节码。

代{过}{滤}理类要实现的接口是MethodInterceptor

而且需要一个增强剂的类(Enhancer)

16、JAVA中异常体系

java中的所有异常都来自顶级父类Throwable。Throwble下有两个子类Exception和Error

  • Exeception:不会导致程序终止。分为runTimeExeception和CheckedExeception检查异常。
  • Error:表示程序无法处理的错误,一旦发生错误,将停止程序运行。如内存溢出

17、Gc如何判断对象可以被回收

  • 强引用:就算内存不足也不会被回收
  • 弱引用:内存不足时,发现就会被回收
  • 软引用:发现就会被回收
  • 虚引用:形同虚设,随时都会被回收

18、线程的生命周期,线程有哪些状态

  • 线程通常有五种状态:
    • 创建(新建)
    • 就绪
    • 运行
    • 阻塞
    • 死亡
  • 阻塞的情况又分为三种
    • 等待阻塞:运行线程执行wait()方法会使线程处于等待状态,不能被自动唤醒,必须依靠其它线程调用notifyAll()方法
    • 同步阻塞:运行线程在获取对象的同步锁时,若该同步被其他线程占用,则JVM会把线程放入“锁池”中
    • 其他阻塞:运行的线程执行sleep或join方法,或者发出I/O请求时,JVM会把该线程置为阻塞状态。当sleep状态超时,join等待线程终止或者超时,或者I/O处理完毕,线程会重新进入就绪状态。

19、sleep()、wait()、join()、yield()的区别

  • sleep:sleep 方法是属于 Thread类中的,sleep 过程中线程不会释放锁,只会阻塞线程,让出cpu给其他线程,但是他的监控状态依然保持着,当指定的时间到了又会自动恢复运行状态,可中断,sleep 给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会
  • wait:属于 Object 类中的,wait 过程中线程会释放对象锁,只有当其他线程调用 notify 才能唤醒此线程。wait 使用时必须先获取对象锁,即必须在 synchronized 修饰的代码块中使用,那么相应的 notify 方法同样必须在 synchronized 修饰的代码块中使用,如果没有在synchronized 修饰的代码块中使用时运行时会抛出IllegalMonitorStateException的异常
  • join:等待调用join方法的线程结束之后,程序再继续执行,一般用于等待异步线程执行完结果之后才能继续运行的场景。例如:主线程创建并启动了子线程,如果子线程中要进行大量耗时运算计算某个数据值,而主线程要取得这个数据值才能运行,这时就要用到 join 方法了
  • yield和 sleep 一样都是 Thread 类的方法,都是暂停当前正在执行的线程对象,不会释放资源锁,和 sleep 不同的是 yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。还有一点和 sleep 不同的是 yield 方法只能使同优先级或更高优先级的线程有执行的机会

20、线程安全的理解

多个线程的结果与单线程的结果一致,或者说是多线程运行后的结果是预期的结果

21、Thread、Runable的区别

Thread和Runable实际是继承关系,操作复杂线程推荐使用thread,如果只是执行一个简单线程建议使用runable

22、ThreadLocal的原理和使用场景

通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。而使用ThreadLocal创建的变量只能被当前线程访问,其它线程则无法访问及修改。
Thread.currentThread():获取当前线程的引用,既代码段正在被哪一个线程调用。
  • ThreadLocal的实现原理就是ThreadLocal里面有一个静态的ThreadLocalMap
    • ThreadLocalMap是ThreadLocal里面的一个静态类
    • ThreadLocal的值是放入了当前线程的一个ThreadLocalMap实例中,所以只能在本线程中访问,其他线程无法访问。

ThreadLocal类的应用场景:承载一些线程相关的数据

因为javaee三层架构里面,如果使用事务,要在service层里面进行开启事务(因为处理逻辑业务都是service层),然后又因为如果我们要使用事务,那么就必须保证执行sql语句的connection连接和开启事务的connection连接都要保持是同一个对象,所以我们要确保在service层和dao层的两个connection连接都是同一个,但是怎么保证connection连接对象都是同一个呢
 据,service层处理业务),connection连接对象我们应该是在service层出现的,但是你却放到了dao层,这样数据的处理和逻辑业务的处理没有分离开来,javaee的三层开发就没有他的效果了,所以这一种方式的解决方法不好,所以我们就通过ThreadLocal的方式来存储这个connection对象,这样就能够保证在service层和dao层的数据保证一致了

23、并发、并行、串行的区别

  • 串行:在时间上不可能发生重叠,前一个任务没弄完,下一个任务就只能等待
  • 并行:在时间上是重叠的,两个任务在同一时刻互不干扰的同时执行
  • 并发:允许两个任务彼此干扰。同一时间点,只有一个任务运行,交替执行

24、并发的三大特性

  • 原子性
    • 不可中断,要么全部执行,要么全部不执行
    • 关键字:synchronized
  • 可见性
    • 对其他线程的可见性,a修改了线程的值,其它线程也能发现
    • 关键字:synchronized、volatile、final
  • 有序性
    • 虚拟机在编译时,对于那些改变顺序之后不会对最终结果造成影响的代码,虚拟机不会按照我们期望的循序执行,有可能对他们重新排序,实际上,对于那些代码重新排序之后,虽然对变量的值没有造成影响,但是,可能会出现线程安全问题
    • 关键字:synchronized、volatile

25、为什么用线程池?解释下线程池的参数?

  • 频繁的创建和销毁线程,比较的消耗资源
  • 提高线程的可管理性

    corePoolSize:代表核心线程数,也就是正常情况下创建工作的线程,这些线程创建后并不会消除,而是一种常驻线程
    maxinumPoolSize:代表最大线程数,表示最大允许创建的数量。
    keepAliveTime:代表超出核心线程之外的空闲存活时间。
    workQueue:用来存放执行的任务
    ThreadFactory:线程工厂,用来生产线程执行任务
    Handler:任务拒绝策略。有两种:(1)当我们调用shutdown等方法来关闭线程池后,但在线程池内还有没有完成的任务,我们还想继续提任务,但是由于线程池已经关闭,就会遭到拒绝。(2)当线程已经达到最大线程数,已经没有能力提交新的任务,也会遭到拒绝。

26、线程池中线程复用原理

首先线程池会有一个管理任务的队列,这个任务队列里就是存放着各种任务,线程池会一直不停的循环的去查看消息队列里有没有接到任务,如果没有,则继续循环,如果有了则开始创建线程。

27、Spring是什么

  • Spring是一个开源框架
  • Spring为简化企业应用开发而生

28、谈谈你对AOP的理解

切面编程,解耦合,不破坏代码结构

29、谈谈你对IOC的理解

控制反转,传统是new一个对象,而用了spring交给spring去管理,创建对象。
第一步:编写applicationContext.xml文件,固定的,不需要自己创建。找个项复制来就行。
第二步:在此文件中配置想交给spring容器管理的对象实例。
第三步:加载applicationContext.xml文件,得到applicationContext对象实例,
第四步:调用getBean方法拿到配置的实例对象。

30、BeanFactory和ApplicationContext有什么区别

BeanFactory:在启动中不会实例化Bean,在拿取的时候才会。

ApplicationContext:启东时就会实例化。

31、springBean生命周期

  • Spring容器根据配置中的bean定义实例化bean。
  • Spring使用依赖注入填充所有属性,如bean中所定义的配置。
  • 如果bean实现BeanNameAware接口,则工厂通过传递自身的实例来调用setBeanName()
  • 如果bean实现了BeanFactoryAware接口,工厂传递自身的实例来调用setBeanFactory()
  • 如果存在与bean关联的任何BeanPostProcessors,则调用preProcessBeforeiniyialization()方法
  • 如果bean指定了init方法(<bean>的init-method属性),那么将调用他。
  • 如果存在与bean关联的任何BeanPostProcessors,则将调用postProcessAfterinitialization()方法
  • 如果bean实现DisposableBean接口,当Spring容器关闭时,会调用destory().
  • 如果为bean指定了destroy()方法(<bean>的destroy-method 属性),那么将调用它。

32、spring benan的作用域

  • Singleton:每个spring ioc容器仅有一个单实例
  • prototype:每次请求都会产生一个新的实例
  • Request:每次HTTP请求都会产生一个新的实例,且该bean仅在当前Http请求有效
  • session:每次HTTP请求都会产生新的bean,且只在当前Http Session有效
  • global-session:在一个全局的Http Session中一个bean对应一个实例。(该作用域仅在基于web的Spring ApplicationContext情形下有效)

33、Spring框架中的单例Bean是线程安全的吗?

不是,Spring框架并没有对单例bean进行任何多线程的封装处理。关于单例bean的线程安全和并发问题需要开发者自行去搞定。但实际上,大部分的Spring bean并没有可变的状态(比如Serview类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。如果你的bean有多种状态的话(比如 View Model 对象),就需要自行保证线程安全。最浅显的解决办法就是将多态bean的作用域由“singleton”变更为“prototype”。

34、Spring框架中都用到了那些设计模式

  • 代{过}{滤}理模式—在AOP和remoting中被用的比较多。
  • 单例模式—在spring配置文件中定义的bean默认为单例模式。
  • 模板方法—用来解决代码重复的问题。
  • 工厂模式—BeanFactory用来创建对象的实例。
  • 适配器--spring aop
  • 装饰器--spring data hashmapper
  • 观察者-- spring 时间驱动模型
  • 回调--Spring ResourceLoaderAware回调接口

35、事务的并发问题

  • 脏读:一个事务读取到了另一个事物还未提交的数据
  • 虚度:一个事物多次读取同一行数据,读到了不同的结果
  • 幻读:一个事务多次读取同一张表,读到了不同的行数

36、Spring事务的实现方式以及隔离级别

实现方式:加上一个注解@Transactional

隔离级别:

  • 对未提交:啥也不能解决,任由脏读发生
  • 读已提交:解决了脏读问题
  • 可重复读:解决了脏读、幻读(spring默认隔离级别)
  • 串行化度:解决了脏读、虚度、幻读,但是性能差

37、spring事务的传播机制

  • 【掌握】PROPAGATION_REQUIRED: 表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务。绝大多数情况都是用这个
  • 【掌握】 PROPAGATION_SUPPORTS: 表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行,如果没有事务,我也不会创建。有很小一部分会用到这个传播行为

剩下五个了解,几乎用不到。

  • PROPAGATION_MANDATORY 表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常
  • PROPAGATION_REQUIRED_NEW 表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当 前事务会被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
  • PROPAGATION_NOT_SUPPORTED 表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
  • PROPAGATION_NEVER 表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常
  • PROPAGATION_NESTED 表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与PROPAGATION_REQUIRED一样。注意各厂商对这种传播行为的支持是有所差异的。可以参考资源管理器的文档来确认它们是否支持嵌套事务

38、Spring事务什么时候失效

  • 数据库引擎不支持事务
  • @transactional加在private方法上(@Transactional只能加在public方法上,如果需要在private方法中加入事务,可以使用Aspect配transactionManager使用.)
  • 异常被catch
  • 异常类型错误
  • 没有被Spring管理
  • 没有配置TransactionManager

39、什么是bean的自动装配,有哪些方式

开启自动装配,只需要在xml配置文件<bean>中定义"autowire"属性。

<bean id="cutomer" class="com.llt.xxx.Customer" autowire=""/>

autowire属性有五种装配方式:

  • no-这是默认设置,表示没有自动装配
  • byName-根据bean属性名称进行自动装配。
  • byType-根据bean的类型进行自动装配
  • contructor 类似byType,不过应用于构造器的参数,如果一个bean与构造器参数的类型相同,则自动装配,否则导致异常
  • autodetect:如果有默认构造器就是用contructor进行装配,否则使用byType进行自动装配

40、Spring boot、SpringMVC和Spring有什么区别

  • SpringFrame SpringFramework 最重要的特征是依赖注入。所有 SpringModules 不是依赖注入就是 IOC 控制反转。 当我们恰当的使用 DI 或者是 IOC 的时候,我们可以开发松耦合应用。松耦合应用的单元测试可以很容易的进行。
  • SpringMVC Spring MVC 提供了一种分离式的方法来开发 Web 应用。通过运用像 DispatcherServelet,MoudlAndView 和 ViewResolver 等一些简单的概念,开发 Web 应用将会变的非常简单。
  • SpringBoot Spring 和 SpringMVC 的问题在于需要配置大量的参数。

41、SpringMVC工作流程

  • 用户发送请求到前端控制器 DispatcherServlet
  • dispatcherServlet 收到请求调用HandlerMapping处理映射器
  • HandlerMapping找到具体的处理器,生成处理器及拦截器一并返回给DispatcherServlet
  • DispatcherServlet 调用HandlerAdapter处理适配器
  • HandlerAdpter经过适配器调用具体的controller
  • Controller执行完成返回ModelAndView
  • HandlerAdapter将controller执行结果返回给dispatcherServlet
  • DispatcherServlet将ModelAndView传给视图解析器ViewReslover
  • ViewReslover解析后返回具体的视图view
  • 前端控制器根据视图进行视图渲染
  • 最后DispatcherServlet响应给客户

42、spring中的九大主键

  • HandlerMapping:处理映射器
  • HandelrAdapter:适配器
  • HandlerExeptionReslover:捕获异常,交给render方法进行渲染
  • ViewResplver:视图解析器
  • RequestToViewNameTranslator:根据ViewNma查钊View
  • LocaleResolver:国际化
  • ThemeRsolver:解析主题
  • MultiparReslover:文件上传
  • FlashMapManager:用来管理Flash,主要用在重定向传递参数

43、springboot自动配置原理

home.php?mod=space&uid=476974 + home.php?mod=space&uid=1414569 + Spring spi
自动配置由各个starter提供,使用@Configuration+@Bean定义配置类,放到META-INF/spring。factories下
使用spring spi烧苗平META-INF/搜spring.factories下的配置类
使用@import导入自动配置类
@Configuration是一个符合注解,复合注解里边有一个@EnableAutoConfiguration,这个注解的作用就是开启自动装配。

44、如何理解springboot中的Starter

使用spring+SpringMVC,如果需要映入mybatis等框架,需要到xml中定义mybatis需要的bean

starter就是定义一个starter的jar包,写一个@Configuration配置类,将这些bean定义在里面,然后在starter包的META-IN/spring。factories中写入该配置类,springboot会按照约定来加载该配置类

开发人员只需要将相应的starter包依赖拖进应用,进行相应的属性配置,就可以直接进行代码开发,使用对应的功能。

45、什么事嵌入式服务器?为什么要使用嵌入式服务器

节省了下载安装tomcat,应用也不需要再打war包,然后放到webapp目录下运行

只需要安装了java虚拟机,就可以直接在上面部署应用程序了

springboot已经内置了tomcat.jar,运行main方法时会去启动tomcat,并利用tomcat的spi机制加载SpringMVC

46、mybatis的优缺点

  • 基于SQL语句编程,解除sql与程序代码的耦合,并重用
  • 与JDBC相比,消除了大量冗余代码
  • 很好的与各种数据库兼容
  • 能够与spring很好地集成

缺点:

  • sql语句的编写工作量大,对开发人员编写sql语句的功底有一定要求
  • sql语句因爱数据库,移植性差,不能随意更换数据库

47、#{}和${}的区别

{}:预编译,占位符是以拼接字符连接,提高安全性

${}:字符串替换,是拼接符,容易造成sql注入

48、简述Mybatis的插件运行原理,如何编写一个插件

Mybatis 仅可以编写针对 ParameterHandler、ResultSetHandler、StatementHandler、Executor 这 4 种接口的插件,Mybatis 使用 JDK 的动态代{过}{滤}理,为需要拦截的接口生成代{过}{滤}理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是 InvocationHandler 的 invoke()方法,当然,只会拦截那些你指定需要拦截的方法。

编写插件:实现 Mybatis 的 Interceptor 接口并复写 intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。

49、索引的基本原理

  • 索引用来快速的寻找那些具有特定值的记录,如果没有索引,一般来说执行查询时遍历整张表
  • 索引的原理就是把无序的数据编程有序的查询

50、java创建对象的几种方式

有4种显式地创建对象的方式:

1.用new语句创建对象,这是最常用的创建对象的方式。

2.运用反射手段,调用Java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。

3.调用对象的clone()方法。

4.运用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法.

52、加载ApplicationContext.xml文件的方式有哪些?

  • ClassPathXmlApplicationContext 对象加载
    • 从classpath路径下面去加载配置文件
  • FileSystemXmlApplicationContext
    • 从系统磁盘中加载配置文件

52、Spring创建对象

  • 有参构造:就是需要参数才能够创建对象
  • 无参构造:参构造就是利用反射类的newinstance方法创建对象。
  • 静态工厂:创建一个工厂类,直接类名.方法调用
  • 非静态工厂:先把工厂实例创建,因为非静态方法只能被实例调用

53、依赖注入

  • set注入
  • 构造函数注入
  • 注解注入:@Resource和@Autowired注解注入

54、AOP底层原理

就是动态代{过}{滤}理

JDK动态代{过}{滤}理和CGLIB动态代{过}{滤}理:

  • JDK动态代{过}{滤}理:首先是利用反射来实现的,它是面向接口的,也就是被代{过}{滤}理的目标类需要实现接口才可以被代{过}{滤}理,反射的缺点就是性能不高。

    • 重要方法
      public static Object newProxyInstance(ClassLoader loader,
      Class<?>[] interfaces,
      InvocationHandler h)

    有三个参数,类加载器,接口反射类的数组,InvocationHandler
    代{过}{滤}理类要实现的接口就是InvocationHandler。

55、全局异常捕获

  • @ControllerAdvice:如果有页面返回,那么就是用@ControllerAdvice
  • @RestControllerAdvice:如果只是返回JSON数据,那么就用@RestControllerAdvice

56、实现拦截器的步骤

实现HandlerInterceptor接口,覆写其三个方法,并且交给Spring容器管理,也就是加上@Component注解。其中三个方法的名称:

  • boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)//在控制器方法请求之前执行

  • void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView)//在控制器方法执行完成之后执行。

  • void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex)//视图渲染之后执行

57、SpringMVC和Spring容器的关系

在Spring整体框架的核心概念中,容器是核心思想,就是用来管理Bean的整个生命周期的。Spring和SpringMVC的容器存在父子关系,即Spring是父容器,SpringMVC是其子容器,子容器可以访问父容器的对象,父容器不能访问子容器的类。**例如:Controller中能调用Service,但是Service不能调用Controller。Spring父容器负责所有其他非@Controller注解的Bean的注册,而SpringMVC只负责@Controller注解,处理器映射、视图解析器的Bean的注册,使得他们各负其责、明确边界。配置到子容器的只能是子容器自己访问,配置到父容器的,父子容器都能访问。

58、mysql锁的类型有哪些

基于所得属性分类:共享锁,排它锁

基于锁的粒度分类:行级锁,表级锁,页级锁,间歇锁,临建锁

59、事务的特性和隔离级别

事务基本特性ACID分别是:

  • 原子性:要么全部成功,要么要不失败
  • 一致性:事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少
  • 隔离性:一个事务的修改在最终提交前对其他事物是不可见的
  • 持久性:一个事务一旦提交,事物的操作便永久性的保存在DB中。即使此时再执行回滚操作也不能撤消所做的更改

Redis

60、Rides中的RDB和AOF机制

  • RDB:(快照持久化,默认开启),Redis创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis主从结构,主要用来提高Redis性能),还可以将快照留在原地以便重启服务器的时候使用。
  • AOF:AOF持久化 的实时性更好,默认没有开启,开启AOF持久化后每执行一条会更改Redis中的数据的命令,Redis就会将该命令写入硬盘中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的,默认的文件名是appendonly.aof。

61、redis 内存淘汰机制

redis 提供 6种数据淘汰策略:

  • volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
  • volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
  • volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的)
  • allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  • no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧!

62、redis为什么是单进程单线程

因为单线程代码清晰,线程安全,不用去考虑各种锁

63、为什么redis需要把所有数据放到内存中?

redis为了达到最快的读写速度,将数据都读到内存中,并通过异步的方式将 数据写入磁盘;所以redis具有快速和数据持久化的特征;

64、redis支持的数据类型

  • string值是字符串类型
  • list 值是一个集合
  • set 值是一个无重复数据的集合
  • sorted set 值是一个无重复数据并且排序的集合
  • hash 值可以理解是一个对象;

65、是否使用过Redis集群,集群的原理是什么?

Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master继续提供服务。//哨兵
Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。//集群

66、使用redis有哪些好处?

(1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
(2) 支持丰富数据类型,支持``string``,list,``set``,sorted ``set``,hash
(3) 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
(4) 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除

67、redis的回收策略

最近最少使用的数据淘汰,将要过期的数据淘汰,已经过期的数据淘汰

68、redis 设置过期时间

我们 set key 的时候,都可以给一个 expire time,就是过期时间,通过过期时间我们可以指定这个 key 可以存活的时间。

定期删除:redis默认是每隔 100ms 就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。注意这里是随机抽取的。为什么要随机呢?你想一想假如 redis 存了几十万个 key ,每隔100ms就遍历所有的设置过期时间的 key 的话,就会给 CPU 带来很大的负载!

惰性删除 :定期删除可能会导致很多过期 key 到了时间并没有被删除掉。所以就有了惰性删除。假如你的过期 key,靠定期删除没有被删除掉,还停留在内存里,除非你的系统去查一下那个 key,才会被redis给删除掉。这就是所谓的惰性删除,也是够懒的哈!

69、缓存雪崩、缓存穿透、缓存击穿

缓存雪崩:缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。

  • 解决办法
    • 事前:尽量保证整个 redis 集群的高可用性,发现机器宕机尽快补上。选择合适的内存淘汰策略。
    • 事中:本地ehcache缓存 + hystrix限流&降级,避免MySQL崩掉
    • 事后:利用 redis 持久化机制保存的数据尽快恢复缓存

缓存穿透:一般是黑客故意去请求缓存中不存在的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。

  • 解决办法:
    • 有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。另外也有一个更为简单粗暴的方法(我们采用的就是这种),如果一个查询返回的数据为空(不管是数 据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

缓存击穿:缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力

  • 解决办法

    • 设置热点数据永远不过期。
    • 加互斥锁,互斥锁参考代码如下:
      public static String getData(String key) throws InterruptedException{
      //从缓存读取数据
      String result = getDataFromRedis(key);
      //缓存中不存在数据
      if (result == nul1){
      //去获取锁,获取成功,去数据库取数据
      if (reenLock.tryLock()){
      //从数据库获取数据
      result = getDataFromMysql(key);
      //更新缓存数据
      if(result != null){
      setDataToCache(key,result);
      }
      //释放锁
      rennLock.unlock();
      }
      //获取锁失败
      else{
      //暂停100ms再重新去获取数据
      Thread.sleeo(100);
      result = getData(key);
      }
      }
      return result;
      }

    说明:
    1)缓存中有数据,直接走上述代码13行后就返回结果了

         2)缓存中没有数据,第1个进入的线程,获取锁并从数据库去取数据,没释放锁之前,其他并行进入的线程会等待100ms,再重新去缓存取数据。这样就防止都去数据库重复取数据,重复往缓存中更新数据情况出现。
    
          3)当然这是简化处理,理论上如果能根据key值加锁就更好了,就是线程A从数据库取key1的数据并不妨碍线程B取key2的数据,上面代码明显做不到这点

70、Redis事务

Redis 通过 MULTI、EXEC、WATCH 等命令来实现事务(transaction)功能。在传统的关系式数据库中,常常用 ACID 性质来检验事务功能的可靠性和安全性。在 Redis 中,事务总是具有原子性(Atomicity)、一致性(Consistency)和隔离性(Isolation),并且当 Redis 运行在某种特定的持久化模式下时,事务也具有持久性(Durability)。

71、Shiro

登录流程: 首先前端用户传入用户名个密码,后台创建UsernamePasswordToken,将用户名和密码封装到这个对象中,然后用SecuirityUtil.getSubject()获得Subject对象,Subject对象就是shiro用来登录的对象,调用login(token)方法来执行登录操作,就会进入UserRealm中的dogetAuthcation认证方法,对login方法进行异常捕获,如果抛出异常,则登录失败,如果没有抛出异常,doGetAuthcation返回一个简单的登录信息,表示用户登录成功。

登录成功之后,用注解@RequireRoles和RequirePermissions验证该用户是否有角色和权限。

免费评分

参与人数 3吾爱币 +5 热心值 +3 收起 理由
18238709246 + 1 + 1 不错,刚好我需要!
苏紫方璇 + 3 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
hanlaoshi + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Tamluo 发表于 2021-8-17 18:51
谢谢分享
小丑恶人 发表于 2021-8-17 16:12
hanlaoshi 发表于 2021-8-17 17:11
 楼主| username11 发表于 2021-8-17 17:23

我就是个新手,面试题的话很多是被问到过的,整理了一部分
wm148600 发表于 2021-8-17 18:11
username11 发表于 2021-8-17 17:23
我就是个新手,面试题的话很多是被问到过的,整理了一部分

有文档吗
jiahao163hjl 发表于 2021-8-23 15:09
非常感谢,最近在找0.0
bzb1012 发表于 2023-7-25 20:51
非常感谢
RQHII 发表于 2023-7-28 19:09
谢谢大佬
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-2 17:29

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表