并发设计案例
06并发设计案例
40Disruptor
优化点
内存分配优化
采用ringbuffer数据结构
数组序号长度为二的n次方,真实下标计算时使用二级制与,比模取余更快
数组中的对像在数组初始化时也全部初始化。提升CPU缓存命中率,防止垃圾回收。消费后不删除,生产时覆盖
避免伪共享
伪共享:由于共享缓存行导致缓存无效,只能从内存读取数据的场景。
共享:不同核可读取CPU缓存,而不用读取内存
takeIndex 通过填充字节来独占缓存行
无锁生产、消费
缺点
- 使用复杂
- 占用内存高
41 高性能数据库连接池HiKariCP
数据库连接池:c3p0、DBCP、Tomcat JDBC Connection Pool、Druid、HiKariCP
池化资源作用:避免重量级资源的频繁创建和销毁
HiKariCP性能高的原因:
微观:从字节码的角度优化Java代码
宏观:两个数据结构
FastList
将一个Connection创建的多个Statement 保存在数组 Fast中
- 删除时从后往前遍历。添加Statement是S1,S2,关闭时一般是S2,S1
- get(int index) 没有做越界检查。todo
ConcurrentBag
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33// 用于存储所有的数据库连接
CopyOnWriteArrayList<T> sharedList;
// 线程本地存储中的数据库连接
ThreadLocal<List<Object>> threadList;
// 等待数据库连接的线程数
AtomicInteger waiters;
// 分配数据库连接的工具,线程之间传递数据
SynchronousQueue<T> handoffQueue;
// 添加连接
// 将这个连接加入到共享队列 sharedList 中
// 如果此时有线程在等待数据库连接,那么就通过 handoffQueue将这个连接分配给等待的线程
add(){
}
// 获取连接
// 首先查看线程本地存储是否有空闲连接
//1.如果有,则返回一个空闲的连接;
//2. 如果线程本地存储中无空闲连接,则从共享队列中获取。
//3. 如果共享队列中也没有空闲的连接,则请求线程需要等待
borrow(){
}
// 释放连接
// 1.首先将数据库连接状态更改为 STATE_NOT_IN_USE
// 2.之后查看是否存在等待线程
// 如果有,则分配给等待线程;
// 如果没有,则将该数据库连接保存到线程本地存储里
require(){
}- 预分配到本地线程,减少了竞争
- 使用ThreadLocal存储分配到本地线程的连接
- 使用CAS防止共享队列sharedList中的连接重复分配
- 预分配到本地线程,减少了竞争