当前位置:网站首页>JUC总结
JUC总结
2022-07-26 13:16:00 【weixin_43766298】
java.util.concurrent
1. CyclicBarrier
- 可重复使用的屏障:当请求线程达到一定的数量才会放行,放行之后会再次重置待拦截的线程数量
- 代码示例
public static void testCyclicBarrier(){
CyclicBarrier cyclicBarrier =
new CyclicBarrier(4, () -> System.out.println(Thread.currentThread().getName()+":人满开始游戏!"));
class Task implements Runnable{
private CyclicBarrier cyclicBarrier;
public Task(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+":准备就绪");
cyclicBarrier.await();// 一进来就被阻塞并加入等待队列中
System.out.println(Thread.currentThread().getName()+":游戏中...");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
for (int i = 0; i < 8; i++) {
try {
TimeUnit.MILLISECONDS.sleep(500);// 增加间隔时间,让效果更加直观清晰
new Thread(new Task(cyclicBarrier),"线程_"+i).start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- 控制台输出
线程_0:准备就绪
线程_1:准备就绪
线程_2:准备就绪
线程_3:准备就绪
线程_3:人满开始游戏!
线程_3:游戏中...
线程_0:游戏中...
线程_1:游戏中...
线程_2:游戏中...
线程_4:准备就绪
线程_5:准备就绪
线程_6:准备就绪
线程_7:准备就绪
线程_7:人满开始游戏!
线程_7:游戏中...
线程_4:游戏中...
线程_5:游戏中...
线程_6:游戏中...
2. Semaphore
- Semaphore 就是一个信号量,它的作用是单机应用限流,限制某个接口的并发数
- Semaphore的剩余许可量是通过AQS中的state属性进行的记录,获取许可是将该值进行减少,释放许可是将该值进行增加,当没有足够的许可时,线程会加入到阻塞队列中等待其他线程释放许可并唤醒。
- 代码示例
public static void testSemaphore(){
Semaphore semaphore = new Semaphore(3);
class RUN implements Runnable{
private Semaphore semaphore;
public RUN(Semaphore semaphore) {
this.semaphore = semaphore;
}
@Override
public void run() {
String threadName = Thread.currentThread().getName();
try {
System.out.println("剩余许可证:" + semaphore.availablePermits());
semaphore.acquire();// 许可不足的话,当前线程就会被阻塞并且加入等待队列,直到有一个可用的许可证为止,就会被唤醒
System.out.println(threadName + ":获取到许可证,执行任务");
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println(threadName + ":完成任务,释放许可证");
semaphore.release();
}
}
}
for (int i = 0; i < 12; i++) {
new Thread(new RUN(semaphore),"线程"+i).start();
}
}
- 控制台输出
剩余许可证:3
线程0:获取到许可证,执行任务
剩余许可证:2
线程3:获取到许可证,执行任务
剩余许可证:1
线程4:获取到许可证,执行任务
剩余许可证:0
剩余许可证:0
剩余许可证:0
剩余许可证:0
剩余许可证:0
剩余许可证:0
剩余许可证:0
剩余许可证:0
剩余许可证:0
线程3:完成任务,释放许可证
线程0:完成任务,释放许可证
线程7:获取到许可证,执行任务
线程8:获取到许可证,执行任务
线程4:完成任务,释放许可证
线程11:获取到许可证,执行任务
线程7:完成任务,释放许可证
线程11:完成任务,释放许可证
线程1:获取到许可证,执行任务
线程8:完成任务,释放许可证
线程2:获取到许可证,执行任务
线程5:获取到许可证,执行任务
线程2:完成任务,释放许可证
线程1:完成任务,释放许可证
线程5:完成任务,释放许可证
线程9:获取到许可证,执行任务
线程6:获取到许可证,执行任务
线程10:获取到许可证,执行任务
线程6:完成任务,释放许可证
线程9:完成任务,释放许可证
线程10:完成任务,释放许可证
3. CountDownLatch
- CountDownLatch 翻译过来就是倒数的门锁,可以理解为 计数器屏障
- CountDownLatch 的使用场景一:主线程等待,多个子线程完成任务后,进行汇总合并。
// 主线程等待,多个子线程(任务)完成后,进行汇总合并
public static void testCountDownLatch() throws InterruptedException {
long start = System.currentTimeMillis();
CountDownLatch countDownLatch = new CountDownLatch(5);
class RUN implements Runnable{
private CountDownLatch latch;
public RUN(CountDownLatch latch){
this.latch = latch;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+"_开始执行");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
//
}
} finally {
System.out.println(Thread.currentThread().getName()+"_执行完毕,准备对计数器进行 减1操作");
latch.countDown();// 使用CAS 对 AQS的volatile state属性进行-1操作
}
}
}
for (int i = 0; i < 5; i++) {
new Thread(new RUN(countDownLatch)).start();
}
System.out.println("...主线程准备等待...");
// 主线程等待,当计数器state==0,就唤醒主线程往下执行,可设置最大等待时间。
countDownLatch.await();
System.out.println("...主线程完成等待...");
System.out.println("总花费时间__" + (System.currentTimeMillis()-start));
}
...主线程准备等待...
Thread-0_开始执行
Thread-2_开始执行
Thread-3_开始执行
Thread-1_开始执行
Thread-4_开始执行
Thread-0_执行完毕,准备对计数器进行 减1操作
Thread-1_执行完毕,准备对计数器进行 减1操作
Thread-4_执行完毕,准备对计数器进行 减1操作
Thread-3_执行完毕,准备对计数器进行 减1操作
Thread-2_执行完毕,准备对计数器进行 减1操作
...主线程完成等待...
总花费时间__2030
- CountDownLatch 的使用场景二:多个线程等待:模拟并发,请求一进来就被阻塞,让线程一起执行
// 多个线程等待:模拟并发,请求一进来就被阻塞,让并发线程一起执行
public static void testCountDownLatch2() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1);
class RUN implements Runnable{
private CountDownLatch latch;
public RUN(CountDownLatch latch){
this.latch = latch;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+"_阻塞等待");
latch.await();//所有请求都阻塞在这,等待
System.out.println(Thread.currentThread().getName()+"_开始执行");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"_执行完毕");
} catch (Exception e){
e.printStackTrace();
}
}
}
for (int i = 0; i < 4; i++) {
new Thread(new RUN(countDownLatch),"线程"+i).start();
}
TimeUnit.SECONDS.sleep(5); // 主线程休眠 让 子线程请求都准备好
System.out.println("MAIN 线程 使得计数减1... 唤醒所有子线程...");
countDownLatch.countDown();// 主线程休眠后 调用countDown() 是计数器减1 所有的子线程将会被放行
}
线程2_阻塞等待
线程3_阻塞等待
线程0_阻塞等待
线程1_阻塞等待
MAIN 线程 使得计数减1... 唤醒所有子线程...
线程2_开始执行
线程1_开始执行
线程0_开始执行
线程3_开始执行
线程1_执行完毕
线程2_执行完毕
线程0_执行完毕
线程3_执行完毕
边栏推荐
- Kubelet CRI 容器运行时
- Can I take your subdomain? Exploring Same-Site Attacks in the Modern Web
- From January to June, China's ADAS suppliers accounted for 9%, and another parts giant comprehensively laid out the new smart drive track
- The best engineer was "forced" away by you like this!
- RMII, smii, gmii, rgmii interfaces of Ethernet Driver
- Leetcode 2119. number reversed twice
- Flutter prevents scientific counting and removes mantissa invalid 0
- The parent component accesses the methods or parameters of the child component (the child component exposes the method defineexpose)
- B+ tree (5) introduction to MyISAM -- MySQL from getting started to mastering (17)
- B+树(5)myISAM简介 --mysql从入门到精通(十七)
猜你喜欢

File upload and download performance test based on the locust framework

如何面对科技性失业?

AI theory knowledge map 1 Foundation

Unicode文件解析方法及存在问题

Kubernetes apiserver current limiting strategy

Chat system based on webrtc and websocket

终极套娃 2.0 | 云原生交付的封装

JVM: what does the class loading subsystem do? What is it made of? What eight part essay do you need to remember?

How to face scientific and technological unemployment?

1312_ Apply 7z command for compression and decompression
随机推荐
B+ tree (4) joint index -- MySQL from entry to proficiency (16)
pomerium
key&key_ Len & ref & filtered (4) - MySQL execution plan (50)
我们被一个 kong 的性能 bug 折腾了一个通宵
概要设计说明书
Panorama of volcanic engine cloud growth plan: 30 + plans come out together, and military development advantage areas
From January to June, China's ADAS suppliers accounted for 9%, and another parts giant comprehensively laid out the new smart drive track
一笔画问题(中国邮递员问题)
从其他文件触发pytest.main()注意事项
The difference between $route and $route
Example of establishing socket communication with Siemens PLC based on C # open TCP communication
如何面对科技性失业?
Incorrect use of parentdatawidget when the exception was thrown, this was the stack:
1312_适用7z命令进行压缩与解压
关于自动重复调用接口的一种实现方式-反射
JSON数据传递参数&日期型参数传递
Router. Push(), router. Reply(), router. Go()
MySQL data directory (3) -- table data structure MyISAM (XXVI)
HCIP第十二天笔记整理(BGP联邦、选路规则)
Slam 02. overall framework