1、CountDownLatch
- 是Jdk1.5引入的一个工具类,被称作为:倒计数器
- 创建对象时,参数实际为参与的线程数
- 在执行过程中每执行一个线程调用一次countDown方法,计数器值减一,直至为0
- 当调用await方法,方法会等到计数器值变成0,在此之前,线程会进入阻塞状态
该该工具类经常用于等待其他线程执行到某一节点,再继续执行当前线程代码,场景如下:
1、统计线程的执行情况 2、压测中,实现最大强度的并发 3、多线程间通信,如:线程异步调用完接口,获取结果通知
2、CyclicBarrier
- JDK1.5引入的工具类,被称作为:线程栅栏
- 创建对象时,指定栅栏的线程数量(并非只运行一次)
- await:调用该方法使得线程数量达到指定数量之后才一起向下执行其他代码
- barrierAction:线程数量达到指定数量后,自动触发执行指定任务
- 与CountDownLatch最大的区别在于,该对象可以多次触发执行
典型使用场景:
1、数据量比较大时,实现批量插入数据到数据库 2、数据统计,30个线程统计30天的数据,全部统计完后执行汇总
3、Semaphore
- JDK1.5引入的工具,被称作为:信号量
- 创建对象时,指定许可的数量,控制多个线程争抢许可,如果线程数量大于许可数目,会有线程被阻塞直至获取到线程
- acquire: 获取一个许可,如果没有许可就阻塞
- release:释放一个许可
- availablePermits:方法得到可用许可的数目
典型使用场景:
1、代码并发处理限流
以下为实例代码:
package com.milla.study.netbase.expert.concurrent.lock;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Semaphore;
/**
* @Package: com.milla.study.netbase.expert.concurrent.lock
* @Description: <信号量测试>
* @Author: MILLA
* @CreateDate: 2020/6/3 14:21
* @UpdateUser: MILLA
* @UpdateDate: 2020/6/3 14:21
* @UpdateRemark: <>
* @Version: 1.0
*/
public class AbstractQueuedSynchronizerTests {
public static void main(String[] args) throws InterruptedException {
// semaphoreTest();
// countDownLatchTest();
cyclicBarrierTest();
}
private static void cyclicBarrierTest() {
//只要满足有两个线程就继续往下执行
CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> {
System.out.println("两人拼团成功了!!!");
});
int size = 2;
for (int i = 0; i < size; i++) {
String vipNo = "VIP-" + i;
new Thread(() -> {
try {
execute(vipNo);
cyclicBarrier.await();//当所有的部分都指定到await的时候,栅栏才会打开,才会继续往下执行
System.out.println("执行了..");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
System.out.println("所有的任务都执行结束了...");
}
private static void countDownLatchTest() throws InterruptedException {
int size = 5;
//一般是等待线程达到指定个个数就开始一并执行
CountDownLatch countDownLatch = new CountDownLatch(size);
for (int i = 0; i < size; i++) {
String vipNo = "VIP-" + i;
new Thread(() -> {
try {
execute(vipNo);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
}).start();
}
countDownLatch.await();
System.out.println("所有的任务都执行结束了...");
}
private static void semaphoreTest() {
Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < 10; i++) {
String vipNo = "VIP-" + i;
new Thread(() -> {
try {
semaphore.acquire();
execute(vipNo);
} catch (InterruptedException e) {
e.printStackTrace();
}
semaphore.release();
}).start();
}
}
private static void execute(String vipNo) throws InterruptedException {
System.out.println("迎接贵宾[编号:" + vipNo + "] 客人");
Thread.sleep(new Random().nextInt(3000));
System.out.println("欢送[编号:" + vipNo + "] 客人");
}
}