目录
1. CountDownLatch
1.1 概念
让一些线程阻塞直到另一些线程完成一系列操作后才被唤醒。
1.2 CountDownLatch方法(2个)
当一个或多个线程调用await方法时,调用线程会被阻塞。
其他线程调用countDown方法会将计数器减一(调用countDown方法不会被阻塞)
当计数器的值变为0时,因调用await方法被阻塞的线程会被唤醒,继续执行
1.3 DEMO
1.3.1 DEMO-使用之前
以锁门为例,班长需要6位同学都离开教室才可以关门离开
public class CountDownLatchDemo {
public static void main(String[] args) throws Exception{
for (int i = 0; i < 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName()+"\t 上完自习,离开教师");
}, String.valueOf(i)).start();
}
System.out.println(Thread.currentThread().getName()+"\t ************班长最后关门走人");
}
}
输出
0 上完自习,离开教师
main ************班长最后关门走人
2 上完自习,离开教师
3 上完自习,离开教师
5 上完自习,离开教师
4 上完自习,离开教师
1 上完自习,离开教师
会发现此时,班长关门时间错误
1.3.2 DEMO-使用之后
public class CountDownLatchDemo {
public static void main(String[] args) throws Exception {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 0; i < 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t 上完自习,离开教师");
countDownLatch.countDown();
}, String.valueOf(i)).start();
}
countDownLatch.await();
System.out.println(Thread.currentThread().getName() + "\t ************班长最后关门走人");
}
}
输出
0 上完自习,离开教师
3 上完自习,离开教师
1 上完自习,离开教师
2 上完自习,离开教师
5 上完自习,离开教师
4 上完自习,离开教师
main ************班长最后关门走人
1.3.3 DEMO-生活案例,秦灭六国,一统华夏
public class CountDownLatchDemo {
public static void main(String[] args) throws Exception {
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <= 6; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "国,被灭");
countDownLatch.countDown();
}, CountryEnum.getMessageByCode(i)).start();
}
countDownLatch.await();
System.out.println(Thread.currentThread().getName() + "\t ************秦帝国,一统华夏");
}
}
//国家枚举类
public enum CountryEnum {
ONE(1, "齐"),
TWO(2, "楚"),
THREE(3, "燕"),
FOUR(4, "赵"),
FIVE(5, "魏"),
SIX(6, "韩");
Integer retCode;
String retMessage;
CountryEnum(int retCode, String retMessage) {
this.retCode = retCode;
this.retMessage = retMessage;
}
public static String getMessageByCode(int code) {
for (CountryEnum countryEnum : CountryEnum.values()) {
if (countryEnum.getRetCode() == code) {
return countryEnum.getRetMessage();
}
}
return "未找到国家";
}
public Integer getRetCode() {
return retCode;
}
public void setRetCode(Integer retCode) {
this.retCode = retCode;
}
public String getRetMessage() {
return retMessage;
}
public void setRetMessage(String retMessage) {
this.retMessage = retMessage;
}
}
输出
齐国,被灭
燕国,被灭
楚国,被灭
魏国,被灭
赵国,被灭
韩国,被灭
main ************秦帝国,一统华夏
2 CyclicBarrier
和CountDownLatch(减法)相反,是增加到指定数量,才可以做某件事,做加法。
例:集齐7颗龙珠,召唤神龙; 人到齐了才开会
2.1 概念
字面意思:可循环(Cyclic)使用的屏障(Barrier)
让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截多线程才会继续干活,线程进入屏障通过CyclicBarrier的await()方法
2.2 DEMO
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> System.out.println("*****召唤神龙"));
for (int i = 1; i <= 7; i++) {
final int tempInt = i;
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t 收集到第" + tempInt + "龙珠");
try {
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
}
}
3 Semaphore(信号灯,信号量)
3.1 概念
信号量主要用于两个目的,
一个是用于多个共享资源的互斥使用,另一个用于并发线程数的控制
即,多线程,资源用完时,其他未抢到资源的线程等待,前面每释放一个资源,就抢一个资源。
特点:加,减,资源空间伸缩
可代替synchonized和lock
Semaphore(int permits, boolean fair)
permits 资源数量
fair:公平、非公平
3.2 使用场景
争车位;支付接口常用;netty 底层
dubbo 底层 rpc
rpc 底层 nio
3.3 DEMO
public class SemaphoreDemo {
public static void main(String[] args) {
//模拟3个停车位
Semaphore semaphore = new Semaphore(3);
//模拟6个车子
for(int i = 1; i <= 6; i++) {
new Thread(() -> {
try {
//占车位
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "\t 抢到车位");
try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + "\t 停车3秒后离开车位");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}, String.valueOf(i)).start();
}
}
}
输出
1 抢到车位
3 抢到车位
2 抢到车位
3 停车3秒后离开车位
2 停车3秒后离开车位
4 抢到车位
1 停车3秒后离开车位
5 抢到车位
6 抢到车位
6 停车3秒后离开车位
5 停车3秒后离开车位
4 停车3秒后离开车位
当车位满了的时候,其他线程车在等待,有车位被空出时,才有下一个车进来停车
4 参考文献
以上内容均来自于下方视频,博客内容仅作为个人学习笔记记录
【1】Java面试_高频重点面试题 (第一、二、三季)_ 面试 第1、2、3季_柴林燕_周阳_哔哩哔哩_bilibili