中金所面经 2022.9.20
### ArrayList和LinkedList对比
ArrayList:底层是动态数组,可以扩容,适合查询和修改
LinkedList:底层是双向链表,适合增加和删除
二者均不保证线程安全
内存空间占用:ArrayList浪费主要在list列表的结尾会预留一定容量的空间,LinkedList每个元素要花费更多的空间
在于要存储节点的前继与后驱节点
### 内存泄漏,有没有遇到过
- 大量无法回收的资源
- 没有关闭的连接
### OOM
- 对象创建过多
- 一次性读入过大的数据到内存
- 死循环
### 局部性原理
- 时间局部性:如果程序中的某条指令一旦执行,则不久之后该指令可能再次被执行;如果某数据被访问,则不久之后该数据可能再次被访问。强调数据的重复访问。**缓存**
- 空间局部性:一旦程序访问了某个单元,其附近的内存单元也会在不久后被访问
### 虚拟内存
虚拟内存就是说,让物理内存扩充成更大的逻辑内存,从而让程序获得更多的可用内存。虚拟内存使用部分加载的技术,让一个进程或者资源的某些页面加载进内存,从而能够加载更多的进程,甚至能加载比内存大的进程,这样看起来好像内存变大了,这部分内存其实包含了磁盘或者硬盘,并且就叫做虚拟 内存。
### TCP和HTTP对比
TCP:传输层协议,解决数据如何在网络中传输。
http协议是超文本传输协议,是应用层协议,http协议是建立在tcp协议之上的。会主动释放连接。
### cookie和session
cookie是服务器发送给用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一个服务器再发起请求时被携带并发送到服务器上。
session是服务器和客户端的一次会话的过程。
### TCP和UDP对比
UDP是无连接的,TCP是有连接的。
UDP不可靠,TCP可靠。
无序,有序
快,慢
支持一对一,一对多;只能一对一。
实时应用;适用于可靠的。
### 什么是线程安全
多线程情况下,保证数据的最终一致性
### java的线程状态
新建、就绪、运行、阻塞、死亡
### web应用你封装一个request对象到前端会包括哪些数据
### ConCurrentHashMap和HashTable
- HashTable:使用Synchronized加锁
- ConCurrentHashMap:
1.7版本:使用segment+HashEntry结构,给每一个segment加锁。Segment 继承了 ReentrantLock,所以 Segment 是一种可重入锁,扮演锁的角色;HashEntry 用于存储键值对数据。
1.8版本:使用链表+红黑树结构。抛弃了原有的 Segment 分段锁,采用 CAS + synchronized 实现更加低粒度的锁
### synchronized和ReentrantLock
1. 两者都是可重入锁
2. synchronized依赖于JVM而ReentrantLock依赖于API
3. ReentrantLock比synchronized增加了一些功能,可实现公平锁。
### 说出你知道的所有Java里面保证线程安全的方式
- 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据库完整性的操作。所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(**共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程**)
- 乐观锁:假定不会发生并发冲突,只在提交的时候检查是否违反数据完整性。但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。实现方式:一般使用版本号和CAS算法。使用自旋的方式实现
- ThreadLocal:保证变量线程内部隔离
- volatile:保证变量对所有线程的可见性,当volatile变量被修改,新值对所有线程会立即更新,指令有序化
- CountDownLatch:允许一个或多个线程等待其他线程完成操作
- semaphore:信号量
### 反射机制
反射是指在运行过程中,每一个类都能知道这个类的属性和方法。对于任意对象,都能调用它的任意方法和属性。这种动态调用对象的方法成为反射机制。
反射的步骤:
- 获取这个类的对象实例
- 根据Class对象实例获取Constructor对象
- 使用Constructor对象的newinstance方法获取反射类对象
如果要调用方法
- 获取方法的Method对象
- 利用invoke方法调用方法
如何获取反射中的Class对象
1. Class.forName
2. 类名.class
3. 对象名.getClass()
### **动态代理及应用**
- jdk
- cglib
应用:AOP。对多个类的共同功能进行增强,如日志记录。
静态代理:静态代理通常只代理一个类,事先知道要代理的是什么
动态代理:
- 代理一个接口下的多个实现类
- 运行时才知道要代理什么
实现:jdk动态代理:通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口 。JDK 动态代理的核心是 InvocationHandler 接口和 Proxy 类 。
CGLIB 动态代理: 如果目标类没有实现接口,那么 Spring AOP 会选择使用 CGLIB 来动态 代理目标类 。
### 解释数据库范式
- 一范式:强调的是列的原子性,即数据库表的每一列都是不可分割的原子数据项。
- 二范式:要求实体的属性完全依赖于主关键字。所谓完全 依赖是指不能存在仅依赖主关键字一部分的属性。
- 三范式:任何非主属性不依赖于其它非主属性。
### spring ioc aop
- spring:容器。容器创建对象,将它们装配在一起,配置并管理他们的生命周期。
好处:轻量,IOC,AOP,容器,MVC框架,事务管理,异常管理。
- ioc:控制反转,不用自己创建对象,都交给spring创建管理,将所有的bean交给spring管理,在使用的时候通过DI动态注入。组件之间依赖关系由容器在运行期决定,形象的说, 即由容器动态的将某个依赖关系注入到组件之中。
- aop:面向切面编程,将不同类的共同功能进行增强
### 垃圾收集算法
标记清除法:先用可达性分析遍历内存,把存活对象和垃圾对象进行标记,再遍历一遍,将所有标记对象回收。特点:效率低,标记和清除的效率都不高。
标记整理法:利用可达性分析遍历内存,把存活对象和垃圾对象进行标记,将所有存活对象向一段移动,将端边界外的对象回收。特点:适用于存活对象多,垃圾少。
复制算法:将内存按照容量分为大小相等的两块,每次只使用一块,将还存货的对象移动到另一块。特点:不会产生空间碎片,内存利用率低。
分代收集算法:根据内存对象的存活周期,将内存划分为几块,分为新生代和老年代,在新生代中,有大量对象死去和少量对象存货,所有采用复制算法。在老年代中,对象存活率较高,采用标记清除和标记整理法。
完整GC过程
堆被分为不同的区域,新生代(1/3)和老年代(2/3)。
新生代分为:Eden 、to survivor、from survival,他们默认占比8:1:1。
新生代的垃圾回收(minor gc):只有少量对象存货,采用复制算法,只需要少量复制成本就可以完成回收。
老年代的垃圾回收(major gc):使用标记-清除和标记整理算法
- 对象现在Eden中分配,当edne中没有空间分配时发起一次minor gc。
- 在Eden中执行一次gc后,存活的对象会被放入survivor分区。
- Eden中再一次gc,这时会采用复制算法,将Eden和from区一起清理,存活的对象会被复制到to区。
- 移动一次,对象年龄+1,当对象年龄超过阈值,移动到老年代,
- Survivor 区内存不足会发生担保分配,超过指定大小的对象可以直接进入老年代。
- 大对象直接进入老年代,为了避免为大对象分配内存时由于内存不足发生担保分配带来的复制降低效率
- 老年代满了,触发FUll GC
### 锁
悲观锁:所有的并发操作都会造成冲突,屏蔽一切会影响数据库完整性的操作,在每次查询数据库数据时会加锁。
乐观锁:假定不会发生并发冲突,在查询数据时不会加锁,只有在修改数据时会去判断期间数据有没有被更改,使用版本号和CAS实现。
### 缓存
缓存:数据交换的缓冲区
操作数据库缓存:减少磁盘机械读取
操作数据库缓存:减少文件系统IO
应用程序缓存:减少数据库查询
web服务器缓存:减少应用服务器请求
客户端浏览器缓存:减少对网站访问
### 重写和重载
重写:子类对父类方法的重写,核心重写,外壳不变
重载:同一个类下,对同一个方法的参数数量、参数类型、返回类型不同的重载。
### SpringBoot的自动装配
在SpringBoot的启动类中包含了SpringBootConfiguration ComponentScan、EnableAutoConfiguration,其中EnableAutoConfiguration用于自动装配spring.factories文件中的类。
### springboot怎么开启事务
在入口类加上@EnableTracnsactionManagement
具体方法加@Transactional
### spring springmvc springboot和springcloud的区别
spring:一个轻量级IOC容器框架,简洁,编写代码简单
springmvc:spring一个模块,一个web框架,Dispatcher Servlet, ModelAndView 和 View Resolver
springboot是spring 的上层框架,集成了tomcat,简化配置
springColud:构建在springboot之上,关注全局的微服务架构
Spring是**核心**,提供了基础功能;Spring MVC 是基于Spring的一个 **MVC 框架** ;Spring Boot 是为**简化Spring配置**的快速开发整合包;Spring Cloud是构建在Spring Boot之上的**微服务治理框架**。
### 快排思想
利用分治的方法,每次将小于目标数放在左边,大于目标数放在右边,再对左右重复进行。
快排:空间复杂度O(1),时间复杂度O(nlogn),最差O(n^2)
归并:空间复杂度O(n),时间复杂度O(nlogn)
### mysql中事务和隔离级别
A原子性:事务是不可分割的,要么一起成功要么一起失败
C一致性:数据库中数据总是从一种一致状态转变为一种一致状态
I隔离性:事务之间是隔离的,对其他事务不可见
D持久性:持久化
- 读未提交:事务在写的过程中,另一个事务不允许写该数据,但允许读。其他事务可以读取事务未提交的数据,造成脏读。
- 读已提交:事务读数据时,允许其他事务读写。但写时不允许其他事务读写该数据。可能造成不可重复读:两次读取数据不一致。(大部分数据库的默认级别)
- 可重复读:事务在读时,不允许其他事务读写,保证了两次读写的一致性。可能造成幻读,
- 串行:给每一行数据加锁。
脏读:事务A读取事务B修改的数据,事务B回滚,事务读到脏数据
不可重复读:事务A多次读取数据,事务B在事务A读取期间修改数据,导致两次读取数据不一致
幻读:事务A同时操作数据库中一些数据事务B往数据库中插入了一些新数据,导致事务没有修改全部数据,产生幻觉。
### msql设置了可重读后怎么保证不幻读
1、利用快照 2、next-key lock有索引则锁住本身的行、范围则行锁+间隙锁、无索引锁整个表
### 项目中用了[redis],是单点模式还是哨兵模式
redis常见使用方式
- 单点:采用单个redis节点部署架构,没有备用节点实时同步数据,不提供持久化和备份策略,适用于数据可靠性要求不高的纯缓存业务。
优点:架构简单,部署方便。高性价比,高性能
缺点:不保证数据可靠性
- 主从:主从架构,相较于但副本而言最大的特点就是主从实例之间数据实时同步,并提供数据持久化和备份策略
优点:高可靠性,读写分离,从节点可以扩展主节点的读能力,有效应对高并发。
缺点:故障恢复复杂,主库写能力和存储能力受到单机的限制,原生复制的弊端在早期的版本中也会比较突出,如:Redis复制中断后,Slave会发起psync,此时 如果同步不成功,则会进行全量同步,主库执行全量备份的同时可能会造成毫秒或秒级的卡顿;又 由于COW机制,导致极端情况下的主库内存溢出,程序异常退出或宕机;
- 哨兵:主从模式下,主服务器宕机,需要人为切换。这就需要人工干预, 费事费力,还会造成一段时间内服务不可用。这种方式并不推荐,实际生产中,我们优先考虑哨兵 模式。这种模式下,master 宕机,哨兵会自动选举 master 并将其他的 slave 指向新的 master。
优点:Redis Sentinel集群部署简单; 能够解决Redis主从模式下的高可用切换问题; 很方便实现Redis数据节点的线形扩展,轻松突破Redis自身单线程瓶颈,可极大满足Redis大容量 或高性能的业务需求; 可以实现一套Sentinel监控一组Redis数据节点或多组数据节点。
缺点:部署复杂,资源浪费,并不执行故障转移,不能解决读写分离问题,实现起来较为复杂
- 集群:哨兵模式已经可以做到高可用,读写分离,但是这种情况下每台redis服务器都存储相同的内容,造成了极大的资源浪费,reids提出了集群思想,对数据进行分片。
优点:无中心结构,数据按照slot存储分布在多个节点,节点间数据共享,可动态调整数据分布;可扩展性,可以线性拓展到1000个节点,高可用,降低运维成本。
缺点:client端实现复杂,数据通过异步复制,不保证强一致性,节点会因为某些原因发生阻塞(阻塞时间大于clutser-node-timeout),被判断下线,这种 failover是没有必要的。
- redis自研:
### 集合接口和集合类介绍一下
List Set Queue
List:linkedlist Arraylist
### 反射,什么地方用了反射
反射是指在运行过程中,每一个类都能知道这个类的属性和方法。对于任意对象,都能调用它的任意方法和属性。这种动态调用对象的方法成为反射机制。
IoC,创建数据库连接
### 泛型
泛型就是将类型参数化,其在编译时才确定具体的参数
优点:
类型安全
消除强制转换
潜在的性能收益
### jvm内存分区
私有:程序计数器、本地方法栈,线程栈
共享:堆、方法区
程序计数器:记录线程正在执行的字节码所在的行号指示器(下一个)
本地方法栈:调用本地方法,在本地方法栈中分配一块内存
栈:局部变量表,操作数栈,动态链接,方法出口
堆:存放对象
方法区:常量 静态变量 类信息 jdk1.8中被替换为元空间(加载类信息 和 运行时常量池 )运行时常量池存放在堆中
### final、finally、finalize
final:修饰常量,修饰方法表示方法不能重写但能重载,修饰类表示类不可被继承。
finally:与try catch配合使用,表示最终一定会执行
finalize:Object类中的一个方法,在垃圾收集器执行的时候会调用被回收对象的finalize()方法,可以覆盖此方法来实现对其他资源的回收,例如关闭文件等。
### java支持多继承吗?接口和类是否可以多继承
不支持多继承,可以继承多个接口
### 什么是[哈希表](https://www.nowcoder.com/jump/super-jump/word?word=哈希表),影响它性能的两个参数
key-value:加载因子,哈希函数,处理冲突的方法
HashMap:初始容量16 负载因子0.75
### drop、delete、truncate
drop:删除表
delete:删除表中某一条数据
truncate:清空表中数据
### union和union all
union:对两个结果集取并集,不包括重复行,相当于dustinct,同时进行默认规则的排序
union all:对两个结果集进行并集操作,包括重复行,即所有的结果全部显示,不管是不是重复。
### left join和right join
LEFT JOIN 左连接,以左侧表为主,右侧表与其相匹配,匹配不上的记录 ,以null 做替补;RIGHT JOIN右连接,以右侧表为主,左侧表与其相匹配,匹配不上得记录,以null做替补。
### redis的优点
redis本质上是一个key-value的内存数据库,因为是纯内存操作,性能很好。
优点:读写性能优越,支持数据持久化,支持事务,数据结构丰富,支持主从复制,
缺点:数据容量收到物理内存的限制,主机宕机,宕机前有部分数据未能同步到从机,会造成数据不一致问题。
redis是缓存数据库,使用多路复用I/O技术,内存,单线程
### 单例模式的实现方式
饿汉式,懒汉式、枚举(线程安全)
### 死锁,死锁的四个条件
死锁是指两个或者多个事务在同一个资源上相互竞争,并请求锁定对方资源,从而导致恶性循环。
互斥:一个资源一次只能被一个进程使用(不可以破坏)
请求和保持:一个进程因为请求资源而阻塞,对已获得资源不放(一次性分配所有资源)
不可剥夺:进程获得资源在进程完成前,不能强行剥夺(允许强行抢夺资源)
循环等待:循环等待资源的情况(有序分配)
处理死锁
(1)死锁的预防:破坏死锁四个必要条件
(2)死锁的避免:而死锁避免则允许前三个必要条件,但是通过动态地检测 资源分配状态,以确保循环等待条件不成立,从而确保系统处于安全状态。(银行家算法)
(3)死锁检测
(4)死锁接触
### 创建线程的方式,哪一个方式比较好?对比区别
- 实现runnable和callable接口
在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的 情况,从而可以将CPU. 代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
劣势是: 编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法。
- 继承Thred类
编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获得当 前线程。
劣势是: 线程类已经继承了Thread类,所以不能再继承其他父类。
### 线程同步
同步就是协同步调,按照预定的先后次序运行,不是同时运行。线程同步是指多线程通过特定的设置(如互斥量,事件对象,临界区)来控制线程之间的执行顺序(即所谓的同步)也可以说是在线程之间通过同步建立起执行顺序的关系,如果没有同步,那线程之间是各自运行各自的!
线程互斥是指对于共享的进程系统资源,在各单个线程访问时的排它性。当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。
### 线程同步的方式和机制
- 临界区:当多个线程访问一个独占资源,可以使用临界区对象。拥有临界区的线程可以访问被保护起来的资源或者代码段,其他线程若想访问,则被挂起,知道拥有临界区的线程放弃临界区。
- 事件:事件机制,允许一个线程在处理完一个任务后,主动唤醒另一个线程执行任务。
- 互斥量
- 信号量
### TCP的三次握手
- 首先,客户端发送连接请求,向服务端发送一个同步报文(SYN = 1),同时选择一个随机初始序列号seq = x,进入SYN_SETNT状态,等待服务器确认。
- 随后,服务端收到请求,向客户端发送同步确认报文(SYN=1,ACK= 1),确认好为ack = x+1,同时选择一个随机数seq = y作为初始序列号,此时服务器进入SYN_RECV状态。
- 最后,客户端收到服务端确认后,向服务端发送确认报文(ACK=1),确认号为ACK=x+1,seq = y+1,客户端和服务端进入ESTABLISH状态;
### TCP的四次挥手
- 第一次挥手:客户端向服务端发送连接释放报文(FIN=1,ACK=1),主动关闭连接,同时等待服务端确认,seq = u,ack = k。
- 第二次挥手:服务端收到连接释放报文后,立即发出确认报文(ACK=1),序列号seq=k,确认号ack=u+1。
这时 TCP 连接处于半关闭状态,即客户端到服务端的连接已经释放了,但是服务端到客户端的连接 还未释放。这表示客户端已经没有数据发送了,但是服务端可能还要给客户端发送数据。
- 第三次挥手:服务端向客户端发送连接释放报文(FIN=1,ACK=1),主动关闭连接,同时等待A确认
序列号 seq = w,即服务端上次发送的报文的最后一个字节的序号 + 1。 确认号 ack = u + 1,与第二次挥手相同,因为这段时间客户端没有发送数据
- 第四次挥手:客户端收到服务端的连接释放报文,立即发送确认报文(ACK=1),seq=u+1,ack=w+1;
### JAVA Map集合
HashMap,TreeMap,ConCurrentHashMap
### Http和HTTPs
### 浏览器获取页面的整个过程
- 输入网址
- 域名解析
- 建立TCP连接
- 发送Http请求
- 响应HTTP请求,返回前端页面到客户端
- 解析前端页面并渲染
### 多线程的Synchronized
修饰类、代码块、方法、静态方法
悲观锁:假定并发一定会出现冲突,屏蔽一切可能会影响数据库完整性的操作,再读数据时,加锁。
乐观锁:假定不会发生冲突,只有在修改数据的时候会判断数据有没有被修改,使用CAS和版本号。
### TCP三次握手
- 首先,客户端向服务端发送连接请求,并发送同步报文(SYN=1),随机数x作为序列号seq=x;进入SYN_SENT状态
- 随后,服务端收到请求,发送同步确认报文(SYN=1,ACK=1),确认号为ack=x+1,随机数y作为seq=y序列号
- 最后,客户端收到服务端确认请求,发送确认报文(ACK=1),确认号为ack=x+1,序列号seq=y+1
### redis为什么这么快
单线程,内存数据库,非阻塞IO(IO多路复用技术),优化的数据结构,用底层模型不同:Redis直接自己构建了 VM (虚拟内存)机制 ,因为一般的系统调用系统函数的 话,会浪费一定的时间去移动和请求。
### [redis](https://www.nowcoder.com/jump/super-jump/word?word=redis)的常见[数据](https://www.nowcoder.com/jump/super-jump/word?word=数据)类型
string,set,Hash,sortedSet,list,BitMap,Hyperloglog,Geopstial
### mysql的[数据](https://www.nowcoder.com/jump/super-jump/word?word=数据)范式
一范式:原子性,列不可分割
二范式:属性依赖主键,且不存在部份依赖
三范式:任何非主属性不依赖于其它非主属性,不依赖主键之外的其他键
### 关系型和非关系型的区别
关系型数据库:关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织
优点:
- 易于维护
- 使用方便
- 支持复杂操作
缺点:
- 读写性能差
- 灵活性差
- 高并发情况下,硬盘IO是个瓶颈
非关系型数据库:非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。
优点:
- 格式灵活
- 速度快
- 高拓展性
- 成本低
缺点:
- 不提供sql支持
- 无事务处理
- 数据结构复杂
### Tomcat
Tomcat是web容器。你在做web项目时,多数需要http协议,也就是基于请求和响应,比如你在百度输入一行内容搜索,那么百度服务器如何处理这个请求呢,他需要创建servlet来处理,servlet其实就是java程序,只是在服务器端的java程序servlet通过配置文件拦截你的请求,并进行相应处理,然后展示给你相应界面,那么servlet如何创建?
这时候tomcat用到了,它就是帮助你创建servlet的东西,所以也称web容器,没有它,没法运行web项目。相对应的web容器有很多,比如JBOSS,WEBLOGIC等。
Tomcat是一个应用服务器。他可以运行你按照J2EE中的Servlet规范编写好的Java程序。
简单的说它是一个Web网站的运行容器,把你写好的网站放进去就可以运行。
### Servlet
处理请求和发送响应的过程是由一种叫做Servlet的程序来完成的,并且Servlet是为了解决实现动态页面而衍生的东西。
Tomcat 是Web应用服务器,是一个Servlet/JSP容器. Tomcat 作为Servlet容器,负责处理客户请求,把请求传送给Servlet,并将Servlet的响应传送回给客户.而Servlet是一种运行在支持Java语言的服务器上的组件. Servlet最常见的用途是扩展Java Web服务器功能,提供非常安全的,可移植的,易于使用的CGI替代品.
### Springboot的事务怎么开启的?
@EnableTransactionManagement
@Transcational
### 泛型
将类型参数化,在运行时再确定类型。
优点:安全性提高,不需要强制转换类型,提高了代码重用率。
***\*泛型的类型必须是类,不能是基本数据类型。需要⽤到基本数据类型的位置,拿包装类替换。\****
T->java类 E->集合元素 K->键 V->值 ?->不确定的java类型
### 抽象类
1.abstract:抽象的
2.abstract可以用来修饰的结构:类、方法
3.abstract修饰类:抽象类
此类不能实例化
抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全过程)
开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作
4.abstract修饰方法:抽象方法
抽象方法只有方法的声明,没有方法体
包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法的。
若子类重写了父类中的所有的抽象方法后,此子类方可实例化;若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰
abstract使用上的注意点:
1.abstract不能用来修饰:属性、构造器等结构
2.abstract不能用来修饰私有方法、静态方法、final的方法、final的类
### 有哪些方式实现线程安全
- 悲观锁
- 乐观锁
- ThredLocal
- volatile
- CountDownLatch:允许一个或多个线程等待其他线程完成操作
- semaphore:信号量
### 设计模式有哪些
工厂模式,代理模式,适配器模式,原型模式
#### 单例模式
java中最简单的一种模式,一个类只有一个实例。
#### 工厂模式
定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
#### 代理模式
为其他对象提供一种代理以控制对这个对象的访问。
#### 原型模式
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
#### 适配器模式
将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
### GC root
那什么可以作为GC Roots呢?
- 虚拟机栈(栈桢中的本地变量表)中的引用的对象。
- **方法区中的类静态属性引用的对象。**
- 方法区中的常量引用的对象。
- 本地方法栈中JNI的引用的对象。
### 引用计数法
给对象头加一块空间存放引用计数器,放增加一个引用时,引用计数器+1,消除引用-1。
### 并发
并发操作是指同一时间多个用户对同一数据进行读写操作
### 并发的瓶颈
宽带 IO 内存
自己问题
1. 项目介绍一下
2. 项目中遇到了哪些问题
3. 项目的逻辑
4. redis断电数据怎么办(按照redis持久化策略答得不知道对不对)
5. redis怎么保证数据一致性(默认和mysql更新一起答得)
6. redis的事务
7. redis满足原子性吗
8. redis主从复制
9. @controller属于MVC哪一个(当时脑子一抽答了controller层)
10. 内存泄漏
一直在问项目,项目也说的稀烂,问题也答得稀烂
不过问的问题都在总结的面经范围
有缘人加油
#中金所#