Skip to content

Commit 73692d7

Browse files
Update 2022-06-21-java.md
1 parent 6692342 commit 73692d7

File tree

1 file changed

+11
-7
lines changed

1 file changed

+11
-7
lines changed

_posts/2022-06-21-java.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,6 @@ synchronized (obj) {
349349
obj.wait();
350350
}
351351
}
352-
353352
```
354353

355354
synchronized 可以用来修饰非静态方法(普通方法)、静态方法、代码块,锁住的是 class 对象的对象头!
@@ -401,18 +400,19 @@ Java 中的线程分为两种:
401400

402401
计算数组下标是与操作,只有低 n 位进行与操作,高位不参与任何操作 -> 为了增大散列程度减小哈希碰撞,因此将高十六位参与进哈希值的计算。
403402

404-
put() 的流程:
403+
`put()` 的流程:
404+
405405
1. hashcode的高十六位和低十六位进行异或运算
406-
2. (n - 1) & hash 计算数组下标,当 n 为二次幂时,等价于取余操作(n - 1)& hash = hash % n
406+
2. `(n - 1) & hash` 计算数组下标,当 n 为二次幂时,等价于取余操作 `(n - 1)& hash = hash % n`
407407
3. 判断当前下标是否有元素,若有元素,使用尾插法。再根据链表长度判断是否需要转换成红黑树。
408408

409-
第一次扩容:执行第一次 put() 操作时,如果数组为空便会执行第一次扩容操作,初始化数组容量为默认大小。
409+
第一次扩容:执行第一次 `put()` 操作时,如果数组为空便会执行第一次扩容操作,初始化数组容量为默认大小。
410410

411411

412412
扩容的过程:
413413
1. 将数组扩容成原数组的两倍
414414
2. 如果没有哈希冲突的节点,使用 `e.hash&(newCap - 1)` 计算新的桶位置
415-
3. 如果是链表,使用 `e.hash&oldCap` 并且判断是否等于零(本质上判断最高位结果是否为零,例如原 hash 值为
415+
3. 如果是链表,使用 `e.hash&oldCap` 并且判断是否等于零(本质上判断最高位结果是否为零)
416416
1. 如果最高位结果是0,桶位置不变
417417
2. 如果最高位结果是1,桶位置是原位置 + 扩容长度
418418

@@ -436,7 +436,10 @@ NULL key AND NULL value:
436436

437437
ConcurrentHashMap JDK7 vs JDK8
438438
- JDK7: 数组 + 链表。先定位 Segment,再定位桶。底层结构是继承了ReentrantLock的Segment数组。可以看成是由线程安全的HashMap组成的一个map数组,数组的长度决定了支持的最大的并发量。
439-
- JDK8: 数组 + 链表 + 红黑树。可以直接定位到桶。链表中的元素超过8并且数组长度大于64后,将链表结构转换成红黑树。通过对Node数组以CAS方式实现扩容和对Node数组的每个元素的synchronized保证ConcurrentHashMap整体的线程安全。
439+
- JDK8: 数组 + 链表 + 红黑树。可以直接定位到桶。链表中的元素超过8并且数组长度大于64后,将链表结构转换成红黑树。
440+
1. 使用 volatile 修饰Node的值和Next数组以保证值变化时对于其他线程是可见的
441+
2. 使用 table 数组的头结点作为 synchronized 的锁来保证写操作的安全
442+
3. 当头结点为 null 时,使用 CAS 操作来保证数据能正确的写入。
440443

441444
![](https://raw.githubusercontent.com/CompetitiveLin/ImageHostingService/picgo/imgs/202305151605481.png)
442445

@@ -665,6 +668,7 @@ java中静态属性和静态方法可以被继承,但是不能被重写,因
665668
3. 代理模式:`java.lang.reflect` Proxy 类使用动态代理
666669
4. 迭代器模式:`java.util` Iterator 接口使用迭代器遍历集合容器
667670
5. 模板方法模式:`java.util.concurrent.locks` AQS 中的 `tryAcquire`, `tryRelease`, `tryAcquireShared`, `tryReleaseShared` 方法被公平锁和非公平锁重写
668-
6. 装饰器模式 + 适配器模式
671+
6. 建造者模式:线程不安全的 `StringBuilder` 和线程安全的 `StringBuffer`
672+
7. 装饰器模式 + 适配器模式
669673
1. 装饰器模式:通过组合替代继承的方式在不改变原始类的情况下**添加增强功能**,例如 `FilterInputStream``FilterOutputStream` 用于增强 `InputStream``OutputStream` 的功能。
670674
2. 适配器模式:字符流对象和字节流对象的**相互适配**

0 commit comments

Comments
 (0)