并发工具类
Hashtable
- HashMap是线程不安全的(多线程环境下可能会存在问题)。
- 为了保证数据的安全性,我们可以使用Hashtable,但是Hashtable的效率低下
- Hashtable采取悲观锁synchronized的形式保证数据的安全性
- 只要有线程访问,会将整张表全部锁起来,所以Hashtable的效率低下。
1 | package com.yishan.concurrent; |
ConcurrentHashMap
- HashMap是线程不安全的。多线程环境下会有数据安全问题
- Hashtable是线程安全的,但是会将整张表锁起来,效率低下
- ConcurrentHashMap也是线程安全的,效率较高。
ConcurrentHashMap jdk1.7底层原理
创建对象
- 默认创建一个长度为16,加载因子为0.75的大数组,这个大数组一旦创建无法扩容
- 还会创建一个长度为2 的小数组,把地址值赋值给0索引处,其他索引位置的元素都是null
添加
- 如果为null,则按照模板创建小数组
- 创建完毕,会进行二次哈希,计算出小数组中应存入的位置,直接存入
- 如果不为null,就会根据记录的地址值找到小数组
- 二次哈希,计算出在小数组中应存入的位置
- 如果需要扩容,则将小数组扩容两倍
- 如果不需要扩容,则就会小数组的这个位置有没有元素
- 如果没有元素,则直接存
- 如果有元素,就会调用equals方法,比较属性值
- 如果equlas为true,则不存
- 如果equals为false,形成哈希桶结构
只会锁住大数组中的元素及此位置下面的小数组和链表
ConcurrentHashMap jdk1.8底层原理
- 1.如果使用空参构造创建ConcurrentHashMap对象,则什么事情都不做,在第一次添加元素的时候创建哈希表
- 2.计算当前元素应存入的索引
- 3.如果该索引位置为null,则利用cas算法,将本结点添加到数组中
- 4.如果该索引位置不为null,则利用volatile关键字获得当前位置最新的结点地址,挂在他下面,变成链表
- 5.当链表的长度大于等于8时,自动转换成红黑树
- 6.以链表或者红黑树头结点为锁对象,配合悲观锁保证多线程操作集合时数据的安全性
CountDownLatch
使用场景:让某一条线程等待其他线程执行完毕之后再执行
方法:
- CountDownLatch(int count):参数写等待线程的数量,并定义了一个计数器
- await():让线程等待,当计数器为0时,会唤醒等待的线程
- countDown():线程执行完毕时调用,会将计数器-1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package com.yishan.other;
import java.util.concurrent.CountDownLatch;
/**
* @author : yishan
* @date : 2021-01-14 11:39
*/
public class Chile1 extends Thread {
private CountDownLatch countDownLatch;
public Chile1(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("在吃第" + i + "个饺子");
}
//每次调用countDown()方法,计数器-1
countDownLatch.countDown();
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package com.yishan.other;
import java.util.concurrent.CountDownLatch;
/**
* @author : yishan
* @date : 2021-01-14 11:39
*/
public class Chile2 extends Thread {
private CountDownLatch countDownLatch;
public Chile2(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
public void run() {
for (int i = 0; i < 15; i++) {
System.out.println("在吃第" + i + "个饺子");
}
countDownLatch.countDown();
}
}
1 | package com.yishan.other; |
1 | package com.yishan.other; |
1 | package com.yishan.other; |