1、请你说说死锁定义及发生的条件
得分点: 争夺共享资源、相互等待、互斥条件、请求和保持条件、不剥夺条件、环路等待条件
死锁定义: 两个或两个以上的进程在执行过程中,因争夺共享资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁。这些永远在互相等待的进程称为死锁进程
死锁的发生必须具备以下四个必要条件:
-
互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放;
-
请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放;
-
不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放;
-
环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合 {P0,P1,P2,···,Pn} 中的 P0 正在等待一个 P1 占用的资源;P1 正在等待 P2 占用的资源,……,Pn 正在等待已被 P0 占用的资源。
2、说说你对MVC的理解
得分点: mvc概念,model、view、controller模块功能
-
MVC是一种设计模式,将软件分为三层,分别是Model(模型)层,View(视图)层,Controller(控制器)层。其中模型层代表的是数据,视图层代表的是界面,控制器层代表的是逻辑处理,是连接视图与模型之前的桥梁。降低耦合,便于代码的维护
-
Model:指从现实世界中抽象出来的对象模型,是应用逻辑的反应;它封装了数据和对数据的操作,是实际进行数据处理的地方
-
View:负责进行模型的展示,一般就是我们见到的用户界面。
-
Controller:控制器负责视图和模型之间的交互,控制对用户输入的响应、响应方式和流程;它主要负责两方面的动作,一是把用户的请求分发到相应的模型,二是把模型的改变及时地反映到视图上。
3、详细的说说Redis的数据类型
得分点: Redis5种数据结构
redis中常用的五种数据结构:string、list、set、zset、hash。
-
String结构底层是一个简单动态字符串,支持扩容,存储字符串
-
list存储线性有序且可重复的元素,底层数据结构可以是双向链表/压缩列表
-
set存储不可重复的元素,一般用于求交集、差集等,底层数据结构可以是hash和整数数组
-
zset存储的是有序不可重复的元素,zset为每个元素添加了一个score属性作为排序依据,底层数据结构可以是ziplist和跳表
-
hash类型存储的是键值对,底层数据结构是ziplist和hash
4、请你说说乐观锁和悲观锁
得分点: 乐观锁、悲观锁定义及使用场景
-
乐观锁:乐观锁总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。
CAS的全程是:Compare And Swap(比较并交换)==>CAS操作涉及到3个操作符:当前内存中的值、预估值、即将修改的新增,当且仅当预估值等于内存中的值的时候,才将新的值保存到内存中,否则什么都不做
-
悲观锁:悲观锁总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
-
两种锁的使用场景 乐观锁: GIT,SVN,CVS等代码版本控制管理器,就是一个乐观锁使用很好的场景,例如:A、B程序员,同时从SVN服务器上下载了code.html文件,当A完成提交后,此时B再提交,那么会报版本冲突,此时需要B进行版本处理合并后,再提交到服务器。这其实就是乐观锁的实现全过程。如果此时使用的是悲观锁,那么意味者所有程序员都必须一个一个等待操作提交完,才能访问文件,这是难以接受的。 悲观锁: 悲观锁的好处在于可以减少并发,但是当并发量非常大的时候,由于锁消耗资源、锁定时间过长等原因,很容易导致系统性能下降,资源消耗严重。因此一般我们可以在并发量不是很大,并且出现并发情况导致的异常用户和系统都很难以接受的情况下,会选择悲观锁进行。
5、设计模式了解么
得分点: 单例模式、工厂模式
常用的设计模式有单例模式、工厂模式、代理模式、适配器模式、装饰器模式、模板方法模式等等。
-
像sping中的定义的bean默认为单例模式
-
spring中的BeanFactory用来创建对象的实例,他是工厂模式的体现。
-
AOP面向切面编程时代理模式的体现,它的底层就是基于动态代理实现的。
-
适配器模式在springMVC中有体现,它的处理器适配器会根据处理器规则适配相应的处理器执行,模板方法模式用来解决代码重复的问题等
6、说说你对AOP的理解
得分点: AOP概念、AOP作用、AOP的实现方式
AOP面向切面编程。是spring两大核心之一,它是一种编程思想,是对OOP(面向对象编程)的一种补充。它可以对业务逻辑的各个部分进行隔离,降低耦合,提高代码的可重用性。它的底层是通过动态代理实现的。它的应用场景有事务、日志管理等。
AOP的实现方式有两种: JDK动态代理,可以在运行时创建接口的代理实例。 CGLIB动态代理:可以在运行期间创建子类的动态实例。
7、说说Redis的持久化策略
得分点: RDB、AOF
-
Redis4.0之后,Redis有RDB持久化、AOF持久化、RDB-AOF混合持久化这三种持久化方式。
-
RDB持久化是将当前进程数据以生成快照的方式保存到硬盘的过程,也是Redis默认的持久化机制。RDB会创建一个经过压缩的二进制文件,这个文件以’.rdb‘结尾,内部存储了各个数据库的键值对等信息。RDB持久化过程有手动触发和自动触发两种方式。手动触发是指通过SAVE或BGSAVE命令触发RDB持久化操作,创建“.rdb”文件;自动触发是指通过配置选项,让服务器在满足指定条件时自动执行BGSAVE命令。RDB持久化的优点是其生成的紧凑压缩的二进制文件体积小,使用该文件恢复数据的速度非常快;缺点则是BGSAVE每次运行都要执行fork操作创建子进程,这属于重量级操作,不宜频繁执行,因此,RBD没法做到实时的持久化。
-
AOF以独立日志的方式记录了每次写入的命令,重启时再重新执行AOF文件中的命令来恢复数据。AOF持久化的优点是与RDB持久化可能丢失大量的数据相比,AOF持久化的安全性要高很多。通过使用everysec选项,用户可以将数据丢失的时间窗口限制在1秒之内。其缺点则是,AOF文件存储的是协议文本,它的体积要比二进制格式的”.rdb”文件大很多。AOF需要通过执行AOF文件中的命令来恢复数据库,其恢复速度比RDB慢很多。AOF在进行重写时也需要创建子进程,在数据库体积较大时将占用大量资源,会导致服务器的短暂阻塞。AOF解决了数据持久化的实时性,是目前Redis主流的持久化方式。
-
RDB-AOF混合持久化模式是Redis4.0开始引入的,这种模式是基于AOF持久化构建而来的。用户可以通过配置文件中的“aof-use-rdb-preamble yes”配置项开启AOF混合持久化。Redis服务器在执行AOF重写操作时,会像执行BGSAVE命令一样,根据数据库当前的状态生成相应的RDB数据,并将其写入AOF文件中;对于重写之后执行的Redis命令,则以协议文本的方式追加到AOF文件的末尾,即RDB数据之后。 通过使用RDB-AOF混合持久化,用户可以同时获得RDB持久化和AOF持久化的优点,服务器既可以通过AOF文件包含的RDB数据来实现快速的数据恢复操作,又可以通过AOF文件包含的AOF数据来将丢失数据的时间窗口限制在1s之内
8、请你讲讲单例模式、请你手写一下单例模式
得分点: 饿汉式单例模式、懒汉式单例模式、线程安全的懒汉式单例模式
单例模式(Singleton Pattern)是最简单的创建型设计模式。它会确保一个类只有一个实例存在。单例模式最重要的特点就是构造函数私有,从而避免外界直接使用构造函数直接实例化该类的对象。 单例模式在Java种通常有两种表现形式:
-
饿汉式:类加载时就进行对象实例化
-
懒汉式:第一次引用类时才进行对象实例化
饿汉式单例模式: 在类被加载时就会初始化静态变量instance,这时候类的私有构造函数就会被调用,创建唯一的实例。
饿汉式单例模式:
public class Singleton {
private static Singleton instance = new Singleton();
// 构造方法私有,确保外界不能直接实例
private Singleton() {
}
//通过公有的静态方法获取对象实例
public static Singleton getInstance() {
return instance;
}
}
懒汉式单例模式:
public class Singleton {
private static Singleton instance = null; // 私有构造方法,确保外界不能直接实例化。
private Singleton() {
} // 通过公有的静态方法获取对象实例
public static Singleton getInstace() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
如果线程A和B同时调用此方法,会出现执行if (instance == null)
语句时都为真的情况,那么线程AB都会创建一个对象,那内存中就会出现两个对象,这违反了单例模式的定义。为解决这一问题,可以使用synchronized关键字对静态方法 getInstance()进行同步
线程安全的懒汉式单例模式 代码如下:
public class Singleton {
private static Singleton instance = null;
// 私有构造方法,确保外界不能直接实例化。
private Singleton() {
} // 通过公有的静态方法获取对象实例
synchronized public static Singleton getInstace() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
-
饿汉式单例类在资源利用效率上不如懒汉式单例类,但从速度和反应时间来看,饿汉式单例类要优于懒汉式单例类
-
单例模式的优点: 在一个对象需要频繁的销毁、创建,而销毁、创建性能又无法优化时,单例模式的优势尤其明显 - 在一个对象的产生需要比较多资源时,如读取配置、产生其他依赖对象时,则可以通过在启用时直接产生一个单例对象,然后用永久驻留内存的方式来解决 - 单例模式可以避免对资源的多重占用,因为只有一个实例,避免了对一个共享资源的并发操作 - 单例模式可以在系统设置全局的访问点,优化和共享资源访问
-
单例模式的缺点: 单例模式无法创建子类,扩展困难,若要扩展,除了修改代码基本上没有第二种途径可以实现 - 单例模式对测试不利。在并行开发环境中,如果采用单例模式的类没有完成,是不能进行测试的 - 单例模式与单一职责原则有冲突。一个类应该只实现一个逻辑,而不关心它是否是单例的,是不是要用单例模式取决于环境
9、 说说你对IoC的理解
得分点: 控制反转与依赖注入含义
IoC:控制反转。控制:对象的创建的控制权限;反转:将对象的控制权限交给spring。之前我们创建对象时用new,现在直接从spring容器中取,维护对象之间的依赖关系,降低对象之间的耦合度。 实现方式为DI,依赖注入,有三种注入方式:构造器、setter、接口注入
10、请你说说MySQL的事务隔离级别
得分点: 读未提交、读已提交、可重复读、串行化
-
事务隔离级别是为了解决脏读、不可重复读、幻读
-
脏读:一个事务读取了另一个事务未提交的数据
-
不可重复读:事务A两次读取的数据不一致,读第二次之前可能有其他事务修改了这个数据并提交了
-
幻读:事务A两次读取数据库,两次查询结果的条数不同,称为幻读。
行数变了即为幻读,数据变了即为不可重复度
-
事务隔离级别如下 :
标签:AOF,Singleton,八股文,每日,模式,单例,RDB,Java,持久 From: https://www.cnblogs.com/jxzy/p/17332844.html
读未提交 :以上三个问题都解决不了
读已提交 :只能解决脏读
可重复读:mysql的默认隔离级别,能解决脏读和不可重复读,包含了间隙锁,可以防止幻读
串行化:都可以解决(为每个读取操作加一个共享锁)