共计 3770 个字符,预计需要花费 10 分钟才能阅读完成。
本文首发于 cartoon 的博客
转载请注明出处:https://cartoonyu.github.io/c…
java
对 synchronized 的了解
- java 的一个关键字,用于重量级锁的设定
- 利用 synchronized 关键字,可以实现对互斥资源的访问
作用范围
- 普通方法,锁的粒度为当前对象
- 静态方法,锁的粒度为当前类的 class 对象
- 代码块,锁的粒度为括号内使用的对象
多线程的同步机制
- 使用同步代码块 synchronized
- 通过标志位轮询访问临界资源
- 通过 Condition 以及 lock 对资源的锁定以及释放
- 通过阻塞队列 BlockQueue(生产者 / 消费者)
threadLocal 的概念以及使用场景
- 每个线程都能拥有该变量的独立副本
内部通过 ThreadLocalMap 进行值的存储以及读取
初始容量为 16
- 负载因子为 2 /3
- 通过再 hash 法解决 hash 冲突
final,finally,finalize 的区别
- final 为不可变修饰词,用于声明属性,方法或类不可变
- finally 为异常捕获机制一部分,总是会被执行。若 try 或 catch 有 return 语句,finally 早于此 return 语句执行
- finalize 为 Object 方法,调用此方法可以实现资源的回收,但是回收时间由 JVM 决定
java 注解的作用
- 生成文档
- 完成特定的标识(@Service 等)
- 在编译时进行格式检查(@Override)
java 集合间的区别
- set 与 list 都只含单个元素,而 Map 含有 key-value 对
- Map 将 entry 数组置为 null,就是 set,所以 set 内元素是无序的,list 元素是有序的
BIO NIO AIO 的区别
BIO
同步阻塞
- 线程阻塞进行运算后返回结果
NIO
同步非阻塞
- 请求共用一个线程进行处理
- 线程会直接返回结果到请求
AIO
异步非阻塞
- 线程处理后会通过回调返回结果
java 反射机制的理解
作用
- 在程序运行中,动态获取对象所属类,属性以及方法等信息
- 在程序运行时,动态改变对象属性
- 动态代理以及静态代理
jvm
怎么判断对象是否可回收?
- 引用计数法
- 可达性分析算法(GC ROOT)
java 内存区域划分
- 运行时数据区域
线程共享
- 方法区
- 栈
线程隔离区
- 虚拟机栈
- 本地方法栈
- 程序计数器
数据库
MyBatis 分页方式以及区别
逻辑分页
- 数组分页
- RowBounds 分页
物理分页
- sql 分页
- 拦截器分页
数据库事务特性以及隔离级别
特性
原子性(Atomicity)
- 事务执行结果是一致的,成功或者回滚
一致性(Consistency)
- 事务执行前后数据库状态不受影响
隔离性(Isolation)
- 事务间操作相互独立
持久性
- 事务执行产生的结果是永久存储下来的
隔离级别
read uncommitted
- 读取事务未提交的数据
read commited
- 多次查询某一数据结果不一致
repeatable
- 同时修改同一元素造成事务提交结果发生偏差
serializable
- 事务的顺序执行
redis 的数据类型以及底层数据结构
string
- 通过 DDS(简单的动态字符串)实现
- DDS 的实现通过双端链表实现
hash
压缩列表(数据量较小)
- key-value 对少于 512 个且所有键对大小都要小于 64 字节
散列表
- 链地址法解决冲突
set
有序数组
- 数据都是整数
- 元素个数不超过 512 个
- 散列表
list
- 压缩列表
双循环链表
- 所有数据大小小于 64 字节
- 数据个数小于 128 个
有序集合
压缩列表
- 类似于数组,存储空间是连续的,但是元素所占空间不唯一
- 双循环链表
缓存穿透的概念,解决方法
- 缓存穿透是指请求访问不存在的 key,请求穿透到 DB,流量大会造成 DB 崩溃
解决方法
- 采用布隆过滤器或者 BitMap 对请求进行过滤
缓存雪崩的概念,解决方法
- 大量 key 设置统一过期时间,造成瞬间 DB 访问量过大
解决方法
- key 的过期时间用随机数进行设置
缓存击穿的概念,解决方法
- 存在 key 在缓存失效的瞬间被大量请求访问,造成 DB 请求量大
解决方法
- 设置短期 key 替代原始 key
- key 再生成后删除短期 key
spring
AOP,IOC 的概念
AOP
- AOP 面向切面编程,它将原本纵向的程序看作成一个个切面的组合,是 OOP 的补充
- 动态插入执行逻辑到原有执行流程中
- 通知(Advice): 具体实现逻辑
- 连接点(JoinPoint): 使用通知的位置
- 切入点(PointCut): 指定使用通知的连接点位置
- 切面(Aspect): 通知与切入点集合
- 引入(introduction): 添加新方法属性到现有类中
- 目标(target): 被通知的对象
- 代理(proxy)
- 静态代理
- 动态代理
- 织入(weaving): 将切面引用到目标对象生成代理对象的过程
IOC
- 我把 IOC 称作为控制反转或者依赖注入,IOC 是 Spring 的核心思想,它使调用者不用管理对象的生存周期以及具体实现,能够更加注重于业务逻辑的实现。
- 在平时实际开发中,我通常使用向上转型的对象完成业务逻辑,这样我觉得能使对象中的耦合度降低,而且在代码重构的时候能够轻易切换实现类。
Spring bean 的作用域
- singleton
- prototype
- session
- request
- global session
Spring bean 是线程安全吗?
- prototype,request 每次被调用都会创建新对象,不存在线程问题
- singleton,session,globalSession 会造成线程间竞争,无状态 bean 是线程安全的,有状态 beanSpring 通过 ThreadLocal 进行解决
spring mvc 的执行流程
- 请求通过 http 到达后端,由 DispatcherServlet 进行分发
- DispatchServlet 通过 HandlerMapping 查找处理的 Controller,中间或者会有过滤器等进行处理
- 如果在查找过程中发生错误,HandlerExceptionResolver 会返回一个 HandlerExecutionChain 对象到 DispathchServlet
- 请求正确分发到 Controller,Controller 调用 Service 以及 Repository 等进行处理,调用 RequestAndViewNameResolver 处理后返回 ModelAndView 对象到 DispatchServlet
- DispatchServlet 根据返回的 ModelAndView 对象,将对象交给 ViewResolver 组件进行视图的渲染,如果在语言上有特殊要求,渲染会调用 LocaleResolver 以及 ThemeResolver 进行国际化的适配
网络
Session 与 cookie 的区别
- cookie 存储在客户端,session 存储在服务器
- cookie 只能存储字符串,session 可以存储任意对象
- cookie 的存储大小受客户端影响,大小为 4KB,session 存储大小不受影响
- 后端获取 cookie 通过 http 报文中的 cookie 字段获取,session 则通过 cookie 中的 sessionId 标识寻找
session 的工作原理
- session 是存储在服务器端的一种标识客户端的数据结构
用户请求到达后台,后台检测是否有 sessionId 字段的存在
- 有的话,校验字段是否合法
- 没有的话,创建新 session 并返回对应 sessionId 到客户端
TCP 与 UDP 区别
- TCP 面向连接,UDP 不面向连接
- TCP 有拥塞控制,UDP 没有拥塞控制
- TCP 资源开销大,UDP 资源开销小
- TCP 只支持一对一,UDP 支持一对多
- TCP 提供可靠传输,UDP 尽可能交付
- TCP 面向字节流,UDP 面向报文
tcp 粘包的原因以及解决办法
原因
- 不同数据包在到达接收方时首尾部粘在一起
解决方法
- 在每个 tcp 报文首部添加报文长度
- 在报文的首部或者尾部设置特殊的符号位标识
tcp 的三次握手与四次挥手
三次握手(连接过程)
一次握手(客户端发起)
- 创建 TCB
- 发送 SYN=1,seq=x
- 进入 SYN-SENT
二次握手(服务器发起)
- 发送 ACK=1,syn=1,ack=y+1,seq=x+1
- 进入 SYN-RCVD
三次握手(客户端发起)
- 发送 ACK=1,seq=x+1,ack=x+1
- 进入 ESTABLISHED
四次挥手(结束连接过程)
一次挥手
- 客户端发送 FIN=1,seq= u 为内容的请求报文
- 客户端进入 FIN-SENT- 1 状态
二次挥手
- 服务器端发送 ACK=1,seq=v,ack=u+ 1 为内容的确认报文
- 服务器端进入 CLOSE_WAIT
- 客户端进入 FIN-SENT- 2 状态
三次挥手
- 服务器端发送 FIN=1,seq=w,ACK=1,ack=u+ 1 为内容的释放报文
- 服务器端进入 LAST_ACK 状态
四次挥手
- 客户端发送 ACK=1,ack=w+1,seq=u+ 1 为内容的确认报文
- 客户端进入 TIME_WAIT 状态,等待 2MSL 后关闭连接
- 服务器端接受报文后关闭连接
设计模式
抽象工厂与简单工厂的区别
- 抽象工厂定义创建产品的大概流程,子工厂通过继承抽象工厂负责具体产品的创建,产品种类的增加不需要改变抽象工厂的代码逻辑
- 简单工厂负责具体产品的创建,产品种类的增加需要改变创建的逻辑
算法
快速排序实现
- 主要采用分治的思想
- 定义左右指针遍历元素(左右指针的初始值为边界)
循环遍历数组(左指针小于右指针)
- 循环遍历左指针直到元素大于右指针指向的元素
- 交换左右指针的元素值
- 循环遍历右指针直到元素小于小指针指向的元素
- 交换左右指针的元素值
- 返回左指针的值作为中线
- 分别递归中线左右,依据 2,3 的步骤进行处理