GOGO
2021-03-16 16:41:30 48 举报
AI智能生成
嘻嘻哈哈
作者其他创作
大纲/内容
集合
Map
HashMap
底层数据结构
JDK1.7
数组+链表
头插法
JDK1.8
数组+链表+红黑树
尾插法
扩容机制
初始16
扩容为2倍
负载因子0.75
方便位运算
分布均匀
创建新数组,进行重新移动
resize
线程不安全
重写equals必须重写hashCode
ConcurrentHashMap
安全失败
1.7
数组+链表
segment分段锁
继承ReentrantLock
尝试获取锁存在并发竞争 自旋 阻塞
锁粒度较大
HashEntry
1.8
数组+链表+红黑树
Node
锁node
cas+synchronized
锁粒度变小
线程安全
TreeMap
红黑树
有序(默认是按照key的升序排序)
线程不安全
List
ArrayList
数组
扩容
初始容量为10
原容量1.5倍
线程不安全
查找快/增删慢
LinkedList
双向链表
线程不安全
查找慢/增删快
Vector
数组
线程安全
扩容
初始容量10
2倍
Set
HashSet
其他很多特性和hashmap一样
value为new Object()
TreeSet
基于TreeMap实现
value为new Object()
IO
BIO
阻塞等待连接
阻塞等待数据
每次都是新开一个线程处理并发
耗资源
NIO
非阻塞IO
select / poll /epoll
多路复用(重要)
select
单个进程可监视的fd(文件描述符)数量有限1024个
对socket进行线性扫描,采用轮询的方式,效率低
需要维护一个用来存放大量的fd的一个数据结构,这样使得用户空间和内核空间在传递该结构时复制开销大
poll
解决了select数量限制的问题
大量的fd在用户态和内核地址空间复制
epoll
没有最大并发连接的限制,远大于1024(1G内存可以监听10W个)
效率提高,不是采用轮询的方式,不会随着FD数目的增加而效率下降
利用mmap内存映射,加速了用户态和内核态空间的消息传递;即epoll使用内存映射减少了复制开销
netty
网络
TCP
三次握手
syn seq
syn ack seq
ack seq
目的:为了防止已经失效的连接请求报文段又传送到服务端,因而才生错误
四次挥手
frn ack seq
ack seq
frn ack seq
ack seq
场景
网络会话
文件传输
发送接收邮件
远程登录
如何保证可靠
建立连接实际就是在C/S端开辟空间
客户端开辟空间
服务端开辟空间
双方均开辟空间,建立好socket连接
三次挥手/四次挥手/建立连接是一个原子性的操作
UDP
语音
视频
直播
相对TCP传输数据不是很可靠
粘包/拆包
原因
1. 应用程序写入的数据大于套接字缓冲区大小,这将会发生拆包。
2.应用程序写入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包。
3.进行MSS(最大报文长度)大小的TCP分段,当TCP报文长度-TCP头部长度>MSS的时候将发生拆包。
4.接收方法不及时读取套接字缓冲区数据,这将发生粘包。
解决
1、发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了
2、发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来
3、可以在数据包之间设置边界,如添加特殊符号,这样,接收端通过这个边界就可以将不同的数据包拆分开
HTTP
HTTPS
多线程
synchronized
对象
对象头
mark word
klass Point信息
Monitor
EntryList
Owner
WaitSet
实例数据
array length
填充区
锁方法
ACC_SYNCHRONIZED
锁代码块
monitorenter
monitorexit
程序计数器 count --加减
锁升级
无锁-轻量级-自旋-重量级
无锁
轻量级
自旋
重量级
锁升级过程是不可逆的
Lock
ReentrantLock
NonfairSync
FairSync
AbstractQueueSynchronizer
state
双向链表
ReentrantReadWriteLock
ReadLock
WriteLock
StampedLock
volatile
Java内存模型
主内存
工作内存
可见性
禁止指令重排
原子类
volatile
Unsafe的CAS操作
MESI
跳出死循环
ThreadLocal
ThreadLocalMap
key为ThreadLocal本身
value为不同线程的副本值
内存泄漏
场景
每个线程需要有自己单独的实例
实例需要在多个方法中共享,但不希望被多线程共享
JUC
CountDownLatch
CyclicBarrier
Semaphore
Exchanger?
线程池
参数
核心线程数
最大线程数
线程存活时间
存活时间单位
工作队列
ArrayBlockingQueue
LinkedBlockingQuene
SynchronousQuene
PriorityBlockingQueue
线程工厂
拒绝策略
CallerRunsPolicy
AbortPolicy
DiscardPolicy
DiscardOldestPolicy
死锁必备四个条件
互斥条件:一个资源每次只能被一个进程使用
不可剥夺性:进程已获得资源,在未使用完成前,不能被剥夺
循环等待条件(闭环):若干进程之间形成一种头尾相接的循环等待资源关系
保持和请求条件:一个进程因请求资源而阻塞时,对已获得资源保持不放
JVM
JVM内存模型
线程独享
虚拟机栈
本地栈
程序计数器
线程共享
堆
方法区
类加载机制
加载-验证-准备-解析-初始化-使用-卸载
加载
生成一个class对象
验证
文件格式验证
元数据验证
字节码验证
符号引用验证
准备
默认值
static会分配内存
解析
初始化
父类没初始化时,先初始化父类
使用
卸载
双亲委派机制
避免重复加载
安全
破坏双亲委派的场景
垃圾回收算法
标记复制
适合场景
存活对象少,比较高校
扫描了整个空间
新生代
缺点
双倍空间
需要复制移动对象
标记清除
适合场景
存活对象比较多
老年代
缺点
空间碎片
扫描两次
扫描标记存活对象
扫描清除没标记的对象
标记-整理
引用计数
无法解决循环引用的问题
分代回收
垃圾回收器
CMS
初始标记(STW)
并发标记
重新标记(STW)
并发清理
优缺点
内存碎片
G1
Full GC
老年代写满
system.gc()
永久代/元空间不足
STOP THE WORLD
垃圾收集线程需要暂停用户线程
OOM种类
栈溢出
堆溢出
GC时间过长也会溢出
逃逸分析
可达性
GC Roots对象作为起点进行搜索
虚拟机栈(栈帧中的本地变量表)中引用的对象
方法区中静态属性引用的对象
方法区中常量引用的对象
本地方法栈中(Native方法)引用的对象
java对象分配过程
第一步:通过逃逸分析决定是分配在栈上还是堆上
第二步:如果是在堆上分配,则优先在tlab上分配
第三步:如果tlab上空间不够,则在新生代伊甸园区分配
第四步:如果伊甸园区空间不够,进行一次young gc
第五步:如果young gc之后空间仍然不够则分配至老年代
第六步:如果老年代空间不够,则进行full gc,如果gc之后仍然不够,则oom
JIT(java即时编译)
JVM调优
堆最大值 -Xmx,最小值 -Xms
设置年轻代/老年代绝对大小,防止收缩
OOM
内存泄漏
死锁
GC参数
生产问题排查
内存泄漏
help dump
dump
mat
jmap
OOM
CPU
top
jstack
磁盘
df
网络
netstat
常用框架
Spring
用到哪些设计模式
单例
工厂
适配器
IOC
AOP
静态代理
实现类
动态代理
JDK动态代理
cglib
Bean生命周期
读取配置,生成beanDefination
如果bean实现了beanFactoryPostProcessor,则对beanDefination进行进一步加工
实例化
如果bean实现了beanNameAware,则调用setBeanName方法
如果bean实现了beanFactoryAware,则调用setBeanFactory方法
如果bean实现了BeanPostProcessor,则执行postProcessBeforeInitialization方法
初始化
如果bean实现了BeanPostProcessor,则执行postProcessAfterInitialization方法
当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法
最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法
循环依赖
情况
属性注入可以解决
构造器注入没法解决
缓存 存放
一级缓存放单例bean
二级缓存放bean半成品
三级缓存 工厂 产生bean
为什么要有三级缓存?就只有一级缓存可以吗?
Bean的作用域
singleton
protype
request
session
Mybatis
缓存
一级缓存
二级缓存
优缺点
优点
灵活
解除sql与程序代码的耦合
缺点
对SQL语句依赖程度很高;并且属于半自动,数据库移植比较麻烦
核心运行流程
Hibernate
缓存
Session缓存(事务缓存)
SessionFactory缓存(应用缓存)
优缺点
优点
对象化
更好的移植性
开发效率高
缺点
灵活性和效率不如原生JDBC程序
不适于复杂关系的数据表维护
配置文件复杂
Spring cloud
Ribbon
Feign
Hystrix
zuul
核心filter???
config
Eureka
Eureka客户端
Eureka服务端
Redis
基本数据类型
string
hash
list
set
zset
为什么快
IO多路复用
单线程
C语言
删除策略
定时删除
优点
缺点
定期删除
优点
缺点
惰性删除
优点
缺点
内存淘汰策略
随机
allkeys-random:加入键的时候如果过限,从所有key随机删除
volatile-random:加入键的时候如果过限,从过期键的集合中随机驱逐
频率最少
allkeys-lfu:从所有键中驱逐使用频率最少的键
volatile-lfu:从所有配置了过期时间的键中驱逐使用频率最少的键
最久没有使用的键
allkeys-lru:加入键的时候,如果过限,首先通过LRU算法驱逐最久没有使用的键
volatile-lru:加入键的时候如果过限,首先从设置了过期时间的键集合中驱逐最久没有使用的键
volatile-ttl:从配置了过期时间的键中驱逐马上就要过期的键
noeviction:当内存使用超过配置的时候会返回错误,不会驱逐任何键
持久化策略
RDB
AOF
布隆过滤器
底层就是采用bitmap实现的
高可用/高吞入
其他数据结构
bitmap
pub/sub
geo(地理位置)
HyperLoglog
常见问题
缓存雪崩
原因:大量key同时失效
解决:过期时间加随机值
缓存击穿
原因:缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),大量请求并发请求该数据
解决:热点数据不过期/加互斥锁
缓存穿透
原因:缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求
解决:布隆过滤器
双写一致性
延时双删
主从结构时候怎么办
延时双删时间加长
大key
bigkeys找到,如不需要,进行删除
lazyfree机制
热点key
不过期
多级缓存
布隆过滤器
读写分离
限流
setnx
zset
令牌桶
Mysql
数据库三范式
所有字段值都是不可分解的原子值
每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中
每一列数据都和主键直接相关,而不能间接相关
隔离级别
Read Uncommitted(读取未提交内容)
Read Committed(读取提交内容)
Repeatable Read(可重复读)
Serializable(串行化)
索引
聚集索引
非聚集索引
索引维护
页满了,页分裂,页利用率下降
数据删除,页合并
索引长度
索引选择
普通索引
唯一索引
hash
等值查询
B
页利用率低
B+
MVCC
锁
全局锁
表锁
lock table read/write
读锁不互斥 写锁互斥
行锁
间隙锁
读写锁
innodb怎样加锁
log
undolog
回滚 MVCC
redolog
binlog
分库分表
主从延迟
强制走主
sleep
分库/升配置,降低延迟
高可用/高吞吐
MQ
常见mq
重复消费
消息丢失
消息积压
死信队列
高可用
Zookeeper
选举机制
CAP原则
预提交 ack 2pc
节点
持久化节点
持久化顺序节点
临时节点
临时顺序节点
通知机制
分布式锁
Redis
setnx
过期时间
释放锁对象和上锁对象一致
锁过期,任务没结束?
性能高
redlock
Zookeeper
死锁
羊群效应
临时顺序节点
性能没有redis高
监听watch机制
数据库
效率低
分布式事务
2PC
步骤
准备阶段
提交阶段
问题
同步阻塞
单点问题
数据不一致
太过保守
tcc两阶段补偿事务提交协议
设计模式
单例
工厂
模板方法
适配器
装饰模式
其他基础
序列化与反序列化
序列化:对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。核心作用是对象状态的保存与重建
反序列化:客户端从文件中或网络上获得序列化后的对象字节流,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象
Comparable和Comparator两种比较器
泛型
java8新特性
Lambda 表达式
方法引用(System.out::print)
默认方法
Stream API
简化代码
流式编程
可以并行操作
Date Time API
Optional 类
0 条评论
下一页