Java技术体系
2021-07-05 15:14:19 9 举报
AI智能生成
Java体系
作者其他创作
大纲/内容
软件架构
数据结构
结构
逻辑结构
集合结构
数据元素同属一个集合,相互之间没有任何关联
线性结构
线性表
存储结构
顺序存储结构
顺序表
数组
链式存储结构
静态链表
单链表
双向链表
循环链表
单向循环链表
双向循环链表
栈(特殊线性表)
队列(特殊线性表)
串(字符串)
KMP算法
树形结构
图状结构
补充
线性表,顺序表,链表,数组的区别与联系?
物理结构
顺序结构
链式结构
数据运算
算法
算法
红黑树
五性质
1.每个结点要么是红的要么是黑的。
2.根结点是黑的。
3.每个叶结点(叶结点即指树尾端NIL指针或NULL结点)都是黑的。
4.如果一个结点是红的,那么它的两个儿子都是黑的。
5.对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点。
例图
要点
旋转
左旋
右旋
插入
插入步骤
1.查找插入位置
2.插入后自平衡
删除
设计模式
面向对象七大设计原则
开闭原则(OCP)
里式替换原则(LSP)
依赖倒置原则(DIP)
单一职责原则(SRP)
接口隔离原则(ISP)
最少知识原则(LKP)
合成复用原则(CRP)
23种设计模式
操作系统
编译原理
分布式系统
分布式算法
拜占庭将军问题
关键词
对比
共识(Consensus)
一致性(Consistency)
解决共识问题,达成共识行动一致则成功,不一致则失败。指令本身的真假先不考虑。
目的是在已知有成员不可靠的前提下,所有将军仍能达成一致共识。
本质问题
一致性
节点恶意行为影响共识的成本很低。
正确性
信息不加密,容易被破解,冒充和伪造。
例子
两忠一叛
解决方案
1.口信消息拜占庭将军问题之解
兰伯特论文
如果叛将人数为m,那么将军总数不能少于3m+1,方能解决共识问题。
可理解为增加节点数
缺点
叛将数不确定,无法不停增加节点数。
2.签名消息拜占庭将军问题之解
签名加密
内容无法篡改
将军不能伪造
算法
拜占庭容错算法(byzantine Fault Tolerance, BFT)
存在故障行为,并且还可能有恶意行为
PBFT算法
PoW(Proof of Work)工作量证明算法
非拜占庭容错算法
故障容错算法(Crash Fault Tolerance, CFT)
只有故障行为,没有恶意行为,即只有消息丢失或者重复,而不存在错误消息。
Paxos算法
Raft算法
ZAB协议
拜占庭将军问题与比特币
比特币解决拜占庭将军问题
非对称加密
消息传送的私密性
能够确认身份
签名不可伪造、篡改
扩展
拜占庭将军问题也是密码学领域的核心问题
CAP理论
分布式系统基础理论
CAP三个基础指标
一致性(Consistency)
在分布式系统中的所有数据备份,在同一时刻是否同样的值。
可用性(Availability)
在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。
分区容错性(Partition tolerance)
在分区数据同步失败的情况下,仍然能够提供服务。
CAP不可能三角
即不可能存在CAP型分布式系统,因为P是分布式系统的必要条件,所以分布式系统的可能型只会是AP或者CP。
模型实例
CP模型
强调数据一致性
为了防止数据不一致,集群会拒绝新数据的写入。
典型案例
ZooKeeper
Etcd
HBase
AP模型
强调系统的可用性
分区故障时,相同的读操作,可能会结果不一样。
典型案例
Cassandra
DynamoDB
ACID理论
CAP理论的酸(CP)
强调一致性
ACID是衡量事务的四个特性
ACID说明
原子性(Atomicity,或称不可分割性)
一个事务的所有操作,要么全部完成,要么全部不完成。
一致性(Consistency)
强一致性
是最强的一致性模型,要求任何读取操作都能读取到最新的值,换句话说,要求任何写入操作立即同步给所有进程。
弱一致性
这种一致性级别约束了系统在写入成功后,不承诺立即可以读到写入的值,也不久承诺多久之后数据能够达到一致,但会尽可能地保证到某个时间级别(比如秒级别)后,数据能够达到一致状态
特例
最终一致性
最终一致性是弱一致性的一个特例,系统会保证在一定时间内,能够达到一个数据一致的状态。
隔离性(Isolation)
事务隔离级别
数据库能够防止由于多个并发事务交叉执行而导致数据的不一致。
持久性(Durability)
指事务结束后,对数据的修改是永久的,不会回滚到之前的状态。
可以理解为,操作实现了符合ACID特性,那么这个操作就实现了事务。
分布式事务协议
2PC(Two Phase Commit)二阶段提交协议
原理
提交请求阶段(投票阶段)
由发起节点统计其他节点的执行意愿(假设都OK),则进入后面执行阶段。
提交执行阶段(完成阶段)
发起节点收集各个节点的执行结果后,统一返回。
要点
二阶段提交要求每个阶段必须保证实现自己的承诺,即如果请求阶段阶段承诺成功,那么在执行的时候就不能失败,这样保证了整体的一致性。
应用
目前常用的是XA协议(也叫做X/Open Distributed Transaction Processing即DTP)
XA协议是X/Open国际联盟基于二阶段提交协议提出
MySQL数据库
缺点
在提交请求阶段需要预留资源,即锁定资源,期间其他人不能操作。
数据库是独立的系统,实际上的分布式系统,业务复杂性会远高于数据库系统。
3PC
TCC(Try Confirm Cancel)
原理
Try
预留
这个阶段会收集各个节点返回的请求结果,若都OK,则进入下一步
Confirm
确认
Cancel
撤销
BASE理论
CAP理论的碱(AP)
强调可用性
核心
基本可用(Basically Available)
定义
基本可用指的是分布式系统出现了不可预知故障的时候,允许损失部分可用性。
响应时间合理延长,功能上适当做服务降级。
响应时间合理延长,功能上适当做服务降级。
实现基本可用
软状态(Soft state)
软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。
最终一致性(Eventually consistent)
最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。
Paxos算法
Raft算法
Raft算法
一致性哈希算法
Gossip协议
Quorum NWR算法
PBFT算法
ZAB协议
DDD(领域驱动设计)
序言
互联网架构演进
演进路线
补充
核心思想
业务逻辑不应该依赖于技术框架
基础篇
通用概念
领域
子域
核心域
通用域
支撑域
限界上下文
战术设计
实体(Entity)
值对象(ValueObject)
关联
聚合(Aggregate)
聚合根(AggregateRoot)
进阶篇
领域事件
分层架构
领域服务
重要原则
每层只能位于其下方的层发生耦合
分层情况
接口层
应用层
领域层
基础层
微服务架构模型
整洁架构
洋葱架构
用户界面
应用服务
领域服务
领域模型
六边形架构
子主题
实战篇
加餐篇
图示
聚合中的对象
聚合根
实体
值对象
领域服务
注意事项
领域事件
领域事件基类 DomainEvent
领域事件实体
领域事件的执行逻辑
领域事件数据持久化
仓储模式
DO 与 PO 对象的转换
仓储模式
仓储接口
仓储实现
仓储执行逻辑
工厂模式
服务的组合与编排
注意事项
微服务聚合拆分时的代码演进
微服务拆分前
微服务拆分后
服务接口的提供
facade 接口
DTO 数据组装
总结
聚合与聚合的解耦
微服务内各层的解耦
架构设计
架构理论
CAP
拜占庭将军问题
架构设计三原则
合适原则,演化原则,简单原则
合适优于先进,演化优于一步到位,简单优于复杂
架构基本问题
规模
规模带来的复杂度的主要原因是“量变引起质变”
安全
从技术角度分两类
1.功能上的安全,即代码实现层面
2.网络架构上的安全
防火墙
云服务商承受强大带宽的能力
低成本
各实现环节考虑成本控制问题
可扩展
两个基本条件
正确预测变化,完美封装变化。
预测变化复杂性
不可能每个设计点考虑可扩展性
不可能完全不考虑可扩展性
所有预测都存在出错的可能性
方案
方案一
“变化”封装在变化层,不变的封装在“稳定层”
问题
系统要拆分变化层和稳定层
需要设计变化层和稳定层之间的接口
方案二
提炼抽象层和实现层
抽象层稳定
实现层根据具体业务定制开发
实例有装饰者模式,策略模式等等
3H问题
高可用
高可用架构
独裁式
一主多备
主节点宕机,其中一个备份节点升级为主节点
协商式
一主多从
主节点宕机,其中一个从节点升级为主节点
从节点负责读
与主备架构的区别
mysql
民主式
集群分区
ZooKeeper
高可用分类
应用层
无状态设计。负载均衡,解决分布式Session问题
秒杀系统
服务层
本质是通过冗余来实现高可用。
手段
负载均衡
业务分级
超时重试
异步调用
缓存
缓存预热
冗余
无状态
故障转移
多地多活
过载保护
限流
算法
令牌桶
漏桶
降级
拒绝服务
关闭服务
熔断
幂等
压测
线上压测
线下压测
jmeter等
灰度发布
监控报警
数据层
冗余备份
如何应对副本同步延迟和中断导致的数据一致性问题
数据备份
冷备份
热备份
异步热备份
同步热备份
失效转移
高性能
前端优化
浏览器访问优化
使用浏览器缓存
减少请求次数
启用压缩
减少Cookie传输
前端业务处理代码优化
CDN加速
JS异步
反向代理
应用层优化
使用缓存
集群
异步
代码优化
合理的架构
多线程
资源复用
良好的数据结构
JVM调优
缓存
存储优化
缓存
高性能存储盘
分布式存储
NoSQL
光纤传输
减少数据库IO操作
读写分离
分库分表
高并发
高并发指标
响应时间
吞吐量
QPS
并发用户数
高并发手段
加机器
增加单机性能
并发编程
并发和并行
并发(concurrency)
一个以上任务在一段时间内被执行。可以是同时执行,也可以是分时间片执行。
并行(parallellism)
一个以上的任务同时被执行。
区别
并发是逻辑概念,并行强调物理运行状态。并发包含并行的情况。
三要素
可见性
原子性
有序性
死锁的四个原因
互斥条件
请求和保持条件
不剥夺条件
循环等待
高并发需求
连接数量
请求数量
并发模型
相关
操作系统IO模型
阻塞
非阻塞
同步
非同步
进程模型
单进程
多进程
多线程
分类
操作系统层面
PPC(Process Per Connection)
每次有新连接,新建进程处理
UNIX
缺点
fork代价高
父子进程通信复杂
支持的并发数量有限
prefork
提前创建进程,有新连接直接使用
缺点
同PPC,相对有改进
TPC(Thread Per Connection)
每次有新连接,创建新线程处理。
缺点
高并发仍有性能问题。
无需进程间通信,但是线程间的互斥和共享引入了复杂度,容易死锁。
多线程互相影响的问题,线程出问题,可能导致整个进程退出。
prethread
预先创建线程,有新的连接直接处理。
缺点
同TPC,相对有改进。
框架编程层面
并行worker
单线程回调和事件轮询模型
缺点
会造成大量回调函数的嵌套,代码可读性不佳。
因为没有多线程,在多核的机器上,也没办法实现并行执行。
因为没有多线程,在多核的机器上,也没办法实现并行执行。
案例
Nginx
多进程(单线程)+多路IO复用模型
原理
Nginx启动后,会有一个master进程和多个相互独立的worker进程。
在每个 worker 进程里,Nginx 调用内核 epoll()函数来实现 I/O 的多路复用。
缺点
存在惊群现象。连接进来时,所有子进程都争着处理。
Nginx在accept上加互斥锁应对惊群现象。
Nginx在accept上加互斥锁应对惊群现象。
Node.js
单线程模型
原理
Node.js中所有的逻辑都是事件的回调函数,
所以 Node.js始终在事件循环中,
程序入口就是事件循环第一个事件的回调函数。
所以 Node.js始终在事件循环中,
程序入口就是事件循环第一个事件的回调函数。
缺点
会造成大量回调函数的嵌套,代码可读性不佳。
因为没有多线程,在多核的机器上,也没办法实现并行执行。
因为没有多线程,在多核的机器上,也没办法实现并行执行。
流水线并行
协程模型
MPG(Go并发)
Proactor
Actor
所有的线程(或进程)通过消息传递的方式进行合作,这些线程(或进程)称为Actor。
主角是Actor,类似一种worker,Actor彼此之间直接发送消息,
不需要经过什么中介,消息是异步发送和处理的
主角是Actor,类似一种worker,Actor彼此之间直接发送消息,
不需要经过什么中介,消息是异步发送和处理的
特点
1.所有Actor状态是Actor本地的,外部无法访问。
2.Actor必须只有通过消息传递进行通信。
3.一个Actor可以响应消息,推出新Actor,改变其内部状态。
或将消息发送到一个或多个其他参与者。
或将消息发送到一个或多个其他参与者。
4.Actor可能会堵塞自己,但Actor不应该堵塞它运行的线程。
优点
共享内存更适合单机多核的并发编程,而且共享带来的问题很多,编程也困难。
随着多核时代和分布式系统的到来,共享模型已经不太适合并发编程。
随着多核时代和分布式系统的到来,共享模型已经不太适合并发编程。
应用
MpaReduce
Reactor
Reactor三种典型模式
单Reactor单进程/线程
单Reactor多线程
多Reactor多进程/线程
CSP(Go并发)
Go语言的CSP模型是由协程Goroutine与通道Channel实现
特点
Worker之间通信区别于Actor模式,是通过channel进行消息发布和侦听。
channel使worker之间实现松耦合。
即发送者不知道自己的消息被哪个消费者接收,
消费者也不知道自己接收的哪个发送者的消息。
即发送者不知道自己的消息被哪个消费者接收,
消费者也不知道自己接收的哪个发送者的消息。
优点
Channel不需要缓冲消息,Actor需要。
应用
Go语言
函数性并行
Lambda架构
JDK 1.7 中的 ForkAndJoinPool
架构实践
案例
电商秒杀系统
分布式Session存储
中间件
Netty
1.为什么选netty而不用JDK NIO?
Netty为什么选NIO而不是AIO?
BIO、NIO、AIO详解
2.同类框架,为什么选netty?
Sun Grizzly/Cindy/Jetty/Apple SwiftNIO/ACE/Apache Mina对比
3.粘包和半包问题?
4.编解码
5.keepalive与idle监测
6.netty的锁
7.netty的内存使用
8.netty对reactor的支持
Dubbo
消息队列
RocketMQ
RabbitMQ
Kafka
高吞吐低延迟MQ,使用数据量的流式传输。
如日志、用户活动跟踪、运营指标等等。
如日志、用户活动跟踪、运营指标等等。
ActiveMQ
Apache开源MQ中间件,消息堆积能力不足,一般不考虑。
搜索
ElasticSearch
定时任务
XxlJob
Nginx
安全
常见安全问题
https
XSS
CSRF
哈希洪水攻击
DDos攻击
拒绝服务
审计安全
拖库、洗库、撞库
运维
docker
k8s
技术方向
云
人工智能AI(Artificial Intelligence)
物联网IoT(Internet of Things)
区块链
边缘计算
公开课
1.边缘计算深度调研
2.云走向边缘,云将无处不在
3.边缘计算的发展现状与趋势展望
4.边缘计算在推荐系统中的应用
5.阿里云边缘云原生应用实践
6.KubeEdge
7.用SuperEdge统管边缘设备和机器
8.如何使用k8s管理中国高速公路上的10万边缘节点
9.边缘协同,打通AI最后一公里
10.用EdgeAdm一件安装k8s集群和原生k8s集群
11.基于KubeEdge实现中国移动10086客服云边系统平台
12.Volcano架构设计与原理介绍
13.一文读懂SuperEdge的云边隧道
14.打破内网壁垒,从云端一次添加成百上千的边缘节点
16.2020十大边缘计算开源项目带您深入边缘方向
管理
人
事
物
硬件
计算机组成原理
编程
前端
后端
Java
Java基础
注解
动态代理
反射
类装载器Classloader
根装载器
ExtClassLoader(扩展类装载器)
AppClassLoader(系统类装载器)
IO
内部类
四种内部类
成员内部类
局部内部类
匿名内部类
静态内部类
JVM
深入理解Java虚拟机
第一部分 走进Java
虚拟机实例
一个JAVA程序对应一个虚拟机实例,以main()为开始
内部线程分类
守护线程
非守护线程
虚拟机的退出
所有非守护线程终止
调用exit()方法
虚拟机体系结构
创建新线程
PC寄存器
栈
分类
JAVA栈
本地方法栈
组成
栈帧
JVM的类型
Server VM
Client VM
JVM的工作模式
-Xint
解释模式
-Xcomp
编译模式
-Xmixed
混合模式
类装载子系统
类装载顺序
装载
连接
验证
准备
解析
初始化
第二部分 自动内存管理机制
第1章 运行时数据区
方法区
运行时常量池
字段信息
方法信息
类(静态)变量
指向ClassLoader类的引用
指向Class类的引用
堆
程序计数器
PC寄存器
虚拟机栈
本地方法栈
第2章 HotSpot虚拟机对象探秘
2.1 对象的创建
分配方式
指针碰撞
空闲列表
2.2 对象的内存布局
对象头
自身运行时数据
哈希码
GC分代年龄
锁状态标识
自身持有的锁
偏向线程ID
偏向时间戳
类型指针
实例数据
对齐填充
起占位符的作用
2.3 对象的访问定位
使用句柄
Java堆中划分出一块内存作为句柄池
直接指针
第3章 垃圾收集器与内存分配策略
3.2 对象已死吗?
引用计数算法
弊端:循环引用
可达性算法
GC Roots
虚拟机栈中引用的对象
方法区中静态属性引用的对象
方法区中常量引用的对象
本地方法栈中引用的对象
对象引用
JDK1.2之后扩充
强引用
弱引用
软引用
虚引用
生存还是死亡
回收方法区
3.3 垃圾收集算法
标记-清除算法
缺点:耗时,耗空间
标记、清除效率低
产生大量不连续内存碎片
复制算法
效率高,但是内存缩小为原来一半,空间代价过大
标记-整理算法
对老年代进行标记整理
分代收集算法
新生代
复制算法
老年代
标记清除
标记整理
3.4 Hotspot算法实现
枚举根节点
安全点
GC时所有的线程需要中断。程序可以GC的特殊点。
抢先式中断
主动式中断
安全区域
GC安全的区域
3.5 垃圾收集器
serial收集器
新生代,单线程,复制算法
parnew收集器
新生代,serial的多线程版本,复制算法
parallel scavengel收集器
新生代,多线程,复制算法;达到可控的吞吐量
serial old收集器
老年代,单线程,标记整理算法
parallel old收集器
老年代,多线程,标记整理算法
cms收集器
老年代,多线程并发,标记清除算法
初始标记
并发标记
重新标记
并发清除
G1收集器
优点
并行并发
分代收集
空间整合
可预测的停顿
运行步骤
初始标记
并发标记
最终标记
筛选回收
3.6 内存分配与回收策略
对象优先在Eden分配
大对象直接进入老年代
长期存活的对象将进入老年代
动态对象年龄判定
空间分配担保
第4章 虚拟机性能监控与故障处理工具
4.2 jdk的命令行工具
jps
jstat
jinfo
jmap
jhat
jstack
hsdis
4.3 jdk的可视化工具
jsonsole
visualvm
第5章 调优案例分析与实战
第三部分 虚拟机执行子系统
第6章 类文件结构
6.3 class类的文件结构
类C伪结构
无符号数
u1/u2/u4/u8
表
_info结尾
6.3.1魔数与Class文件的版本
u4:magic_number
0xCAFEBABE(cafe babe)
版本号
u2:minor_version
u2:major_version
版本号从45开始,向前兼容
6.3.2常量池
u2:constant_pool_count
cp_info:constant_pool
主要存放
字面量
文本字符串、final常量
符号引用
类和接口的全限定名
字段的名称和描述符
方法的名称和描述符
6.3.3访问日志
u2:access_flags
6.3.4类索引、父类索引与接口索引集合
u2:this_class
u2:super_class
u2:interfaces_count
u2:interfaces
6.3.5字段表集合
u2:fields_count
field_info:fields
6.3.6方法表集合
u2:methods_count
method_info:methods
6.3.7属性表集合
u2:attributes_count
attribute_info:attributes
6.4字节码指令简介
6.4.1字节码与数据类型
数据类型
基本类型
数值类型
浮点类型
float
double
整数类型
byte
short
int
long
char
boolean
returnAddress
引用类型
类
接口
数组
方法参数传递
按值传递
按引用传递
对象做参数
6.4.2加载和存储指令
6.4.3运算指令
6.4.4类型转换指令
6.4.5对象创建与访问指令
6.4.6操作数栈管理指令
6.4.7控制转移指令
6.4.8方法调用和返回指令
6.4.9异步处理指令
6.4.10同步指令
6.5公有设计和私有实现
6.6class文件结构的发展
第7章 虚拟机类加载机制
7.2类加载的时机
有且只有5种情况立即“初始化”类
new对象时;调用类的静态字段或者方法时
对类反射调用时
初始化类而其父类未初始化时,先初始化父类
虚拟机启动时,初始化主类(包含main方法的类)
JDK1.7动态语言支持,REF_*句柄对应的类
7.3类加载的过程
类的生命周期7阶段
加载
3件事
获取二进制字节流
ZIP读取
网络读取:Applet
运行时计算生成:反射
其他文件生成:JSP
数据库读取:中间件服务器
二进制字节流转化为方法区数据结构
内存中生成java.lang.Class对象
数组类加载
数组类本身由java虚拟机直接创建,
数组类的元素类型由类加载器创建
数组类创建3原则
数组类是引用类型,在类加载器的类名空间上被标识
数组类不是引用类型(int[]),标记为与引导类加载器关联
数组类的可见性与其组件类型一致,组件为非引用类型,默认public
连接
验证
文件格式验证
元数据验证
字节码验证
符号引用验证
准备
在方法区中为类变量(static、final等修饰)分配内存和设置初始值
(准备阶段只赋默认值如0等)
解析
是符号引用替换为直接引用的过程
符号引用
不一定已加载到内存
直接引用
一定已加载到内存
解析动作
类或接口的解析
字段解析
类方法解析
接口方法解析
初始化
真正开始执行类中定义的Java程序代码(字节码)
执行类构造器<clinit()>方法
使用
卸载
7.4类加载器
源起
“通过一个类的全限定名来获取描述此类的二进制字节流”
这个动作在Java虚拟机外部实现
实现这个动作的代码模块称为“类加载器”
类与类加载器
每一个类加载器都有一个独立的类命名空间
双亲委派模型
类加载器种类
启动类加载器
BootStrap Classloader
BootStrap Classloader
C++实现,是虚拟机自身的一部分
扩展类加载器
Extension ClassLoader
Java实现,独立于虚拟机之外
并且全部继承自抽象类:java.lang,ClassLoader
应用程序类加载器
Application ClassLoader
破坏双亲委派模型
第8章 虚拟机字节码执行引擎
8.2运行时栈帧结构
局部变量表
操作数栈
动态连接
方法返回地址
返回信息
8.3方法调用
8.4基于栈的字节码解释执行引擎
第9章 类加载机制执行子系统的案例与实战
第四部分 程序编译与代码优化
第10章 早期(编译期)优化
10.2Javac编译器
10.3Java语法糖的味道
10.4插入式注解处理器
第11章 晚期(运行期)优化
第五部分 高效并发
第12章 Java内存模型与线程
12.2硬件的效率与一致性
12.3Java内存模型
主内存与工作内存
内存间交互操作
八种操作
lock锁定
unlock解锁
read读取
load载入
use使用
assign赋值
store存储
write写入
八条规则
对于volatile型变量的特殊规则
对于long和double型变量的特殊规则
原子性、可见性和有序性
先行发生原则
12.4Java与线程
线程的实现
使用内核线程实现
使用用户线程实现
使用用户线程加轻量级进程混合实现
Java线程调度
协同式
抢占式
状态转换
新建
运行
无限期等待
限期等待
阻塞
结束
第13章 线程安全
13.2线程安全
Java语言中的线程安全
共享数据分类
不可变
绝对线程安全
相对线程安全
线程兼容
线程对立
线程安全的实现方法
互斥同步
非阻塞同步
无同步方案
13.3锁优化
自旋锁与自适应自旋
锁消除
锁粗化
轻量级锁
偏向锁
扩展阅读
垃圾回收算法详解
垃圾收集器图示归纳
JVM示意图
示意图各有特色
1
2 GC各类图示比较全
3
4 JVM全景图(比较全)
5 JVM调优
并发
线程
分类
用户线程
守候线程
创建与启动
三种创建方式
继承Thread类
实现Runnable接口
Executor框架
实现Callable接口
启动
start()方法
常见问题
线程栈模型与线程的变量
线程状态的转换
五大状态
新状态
可运行
运行
等待/阻塞/睡眠
死亡态
Java主流锁
线程要不要锁住同步资源?
锁住
悲观锁
悲观锁认为一个数据发生并发一定会发生修改,所以要对数据的并发操作加锁,悲观锁是比较重量级的锁
子主题
子主题
不锁住
乐观锁
乐观锁认为一个数据发生并发不会发生修改,可以通过版本机制,当发生修改的时候通过不断尝试修改
子主题
子主题
子主题
子主题
子主题
子主题
子主题
子主题
锁住同步资源失败,线程要不要阻塞?
阻塞
不阻塞
自旋锁
适应性自旋锁
多个线程竞争同步资源的流程细节有没有区别?
不锁住资源,多个线程只有一个会成功,其他失败重试
无锁
同一个线程执行同步资源自动获取资源
偏向锁
多个线程竞争同步资源时,没有获取资源的线程自旋等待锁释放
轻量级锁
多个线程竞争同步资源时,没有获取资源的线程阻塞等待唤醒
重量级锁
多个线程竞争锁时要不要排队?
排队
公平锁
先插队,插队失败再排队
非公平锁
一个线程的多个流程能不能获取同一把锁?
能
可重入锁
不能
不可重入锁
多个线程能不能共享一把锁
能
共享锁
不能
排它锁
Sping
Springboot
自动配置原理
SpringBoot 源码常用注解拾遗
@Value
【Spring 提供】
@ConfigurationProperties
【SpringBoot 提供】
@Import
【Spring 提供】
三种使用方式
直接导入普通的 Java 类。
配合自定义的 ImportSelector 使用。
配合 ImportBeanDefinitionRegistrar 使用。
@Conditional
【Spring提供】
@Conditional 注释可以实现只有在特定条件满足时才启用一些配置。
子主题
SpringBoot 启动过程
创建 SpringApplication 对象。
运行run()方法。
SpringBoot 自动配置原理
SpringMVC
SpringFreamwork
Spring编程模型
面向对象编程
契约接口
Aware
BeanPostProcessor
设计模式
对象继承
面向切面编程
动态代理
字节码提升
面向元编程
注解
配置
泛型
函数驱动
函数接口
模块驱动
MavenArtifacts
OSGI Bundles
Java9 Automatic Modules
Spring @Enable*
IoC
IoC简介
IoC主要实现策略
IoC的职责
IoC和DI的区别
IoC容器的实现
Mybatis
Go
Rust
Python
Ruby
存储
数据库
常规
MySQL
Oracle
DM
大数据
数据湖
缓存
redis
Redis设计与实现
第1章 引言
第一部分 数据结构与对象
数据结构
第2章 简单动态字符串
2.1 SDS定义
2.2 SDS与C字符串的区别
获取字符串长度的时间复杂度为O(1)
C字符串获取字符串长度的时间复杂度是O(n),SDS的是O(1),
因为SDS定义结构有长度len属性,而C字符串需要重新计算。
因为SDS定义结构有长度len属性,而C字符串需要重新计算。
杜绝缓冲区溢出
C字符串存在内存溢出覆盖相邻区域内存的问题,SDS修改时会先检查空间大小是否满足需求,
如不够,则先进行空间扩展之后再执行。(空间扩展方案参考2.3)
如不够,则先进行空间扩展之后再执行。(空间扩展方案参考2.3)
减少修改字符串时带来的内存重分配次数
C字符串拼接操作时需要先扩展底层数组空间(否则“缓冲区溢出”);
截断操作时要释放不再使用的空间(否则“内存泄露”)。
截断操作时要释放不再使用的空间(否则“内存泄露”)。
SDS内存分配
空间预分配
SDS进行字符串增长操作,程序会分配必要空间,
同时还分配额外的未使用空间,然后更新free属性值。
同时还分配额外的未使用空间,然后更新free属性值。
分配策略
若对SDS进行修改后,len<1MB,分配与len同样大小的未使用空间。
此时buf数组的实际长度为len+free+1byte(1为表示结束的空字符)
此时buf数组的实际长度为len+free+1byte(1为表示结束的空字符)
若对SDS进行修改后,len>=1MB,则分配1MB的未使用空间。
此时buf数组的实际长度为len+free(1M)+1byte。
此时buf数组的实际长度为len+free(1M)+1byte。
通过空间预分配,减少内存分配次数,将连续增长N次字符串由原来的必定N次重分配降低为最多N次。
当然,缺点是会有一定内存损耗,在当前成本下是可以接受的。
当然,缺点是会有一定内存损耗,在当前成本下是可以接受的。
惰性空间释放
SDS进行字符串缩短操作,程序不会立即使用内存分配来回收多出的空间,而是记录在free属性。
真正需要时,通过SDS提供的API释放。
比如什么具体场景?
二进制安全
C字符串不能包含空字符,导致只能存文本,不能存多媒体(图片、视频、音频、压缩文件等)类的二进制数据。
SDS依据len的属性值判断数组是否结束,所以buf内容可以是任何二进制数据。
仍在buf结尾加上'\0',是为了方便调用C语言API对字符串进行处理,即兼容部分C字符串函数<string.h>。
仍在buf结尾加上'\0',是为了方便调用C语言API对字符串进行处理,即兼容部分C字符串函数<string.h>。
2.3 SDS API
补充
在Redis中的应用
K-V键和值都可能是SDS
用作缓冲区,AOF持久化的缓冲区,以及客户端状态中的输入缓冲区
第3章 链表
3.1 链表和链表节点的实现
3.2 链表和链表节点的API
补充
在Redis中的应用
List
发布与订阅、慢查询、监视器
第4章 字典
4.1 字典的实现
字典(dict)
哈希表(dictht)
哈希表节点(dictEntry)
4.2 哈希算法
4.3 解决键冲突
4.4 rehash
4.5 渐进式hash
补充
在Redis中的应用
Redis数据库、Map
第5章 跳跃表
5.1 跳跃表的实现
补充
在Redis中的应用
zset
在集群节点中用作内部数据
第6章 整数集合
6.1 整数集合的实现
6.2 升级
6.3 升级的好处
6.4 降级
6.5 整数集合API
补充
在Redis中的应用
set
第7章压缩列表
7.1
补充
在Redis中的应用
List、Map
第8章 对象
8.1 对象的类型与编码
8.2 字符串对象
8.3 列表对象
8.4 哈希对象
8.5 集合对象
8.6 有序集合对象
8.7 类型检查与命令多态
8.8 内存回收
8.9 对象共享
8.10 对象的空转时长
第二部分 单机数据库的实现
第9章 数据库
第10章 RDB持久化
第11章 AOF持久化
第12章 事件
第13章 客户端
第14章 服务器
第三部分 多机数据库的实现
第15章 复制
第16章 Sentinel
第17章 集群
第四部分 独立功能的实现
第18章 发布与订阅
第19章 事务
第20章 Lua脚本
第21章 排序
第22章 二进制位数组
第23章 慢查询日志
第24章 监视器
MongoDB
测试
0 条评论
下一页