程序地带

Java面试题集锦(6):CountDownLatch/CyclicBarrier/Semaphore的使用


CountDownLatch

latch:门闩、插销、碰锁、弹簧锁;


如果没有CountDownLatch


class Scratch {
public static void main(String[] args) {
for(int i=0;i<6;i++){
new Thread(()->{
System.out.println(Thread.currentThread().getName()+" 完成");
},String.valueOf(i)).start();
}
System.out.println(Thread.currentThread().getName()+" 最终完成");
}
}

在这里插入图片描述


main线程会直接完成,而不等待其他线程的工作。


使用CountDownLatch


import java.util.concurrent.CountDownLatch;
class Scratch {
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()+" 完成");
countDownLatch.countDown();
},String.valueOf(i)).start();
}
countDownLatch.await();
System.out.println(Thread.currentThread().getName()+" 最终完成");
}
}

使用枚举的CountDownLatch


import jdk.nashorn.internal.objects.annotations.Getter;
public enum CountryEnum{
ONE(1,"齐"),TWO(2,"楚"),THREE(3,"燕"),FOUR(4,"韩"),FIVE(5,"赵"),SIX(6,"魏");
private Integer retCode;
private String retMessage;
CountryEnum(Integer retCode, String retMessage) {
@Getter this.retCode = retCode;
@Getter this.retMessage =retMessage;
}
public static CountryEnum forEach_CountryEnum(int index){
CountryEnum[] myArray = CountryEnum.values();
for(CountryEnum element:myArray){
if(index==element.getRetCOde()){
return element;
}
}
return null;
}
}
import java.util.concurrent.CountDownLatch;
class Scratch {
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()+" 完成");
countDownLatch.countDown();
},CountryEnum.forEach_CountryEnum(i).getRetMessage()).start();
}
countDownLatch.await();
System.out.println(Thread.currentThread().getName()+" 最终完成");
}
public static void close() throws InterruptedException{
CountDownLatch countDownLatch = new CountDownLatch(6);
for(int i=0;i<6;i++){
new Thread(()->{
System.out.println(Thread.currentThread().getName()+" 完成");
countDownLatch.countDown();
},String.valueOf(i)).start();
}
countDownLatch.await();
System.out.println(Thread.currentThread().getName()+" 最终完成");
}
}

小总结:CountDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后再闭锁上等待的线程就可以恢复工作了。 ※CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,调用线程会被阻塞,其它线程调用countDown方法会将计数器减1(调用CountDown的线程不会被阻塞),当计数器的值变为0,调用await方法被阻塞的线程被唤醒,继续执行。


CyclicBarrier

Cyclic 循环,Barrier屏障 (集齐七颗龙珠召唤神龙) CyclicBarrier :可循环使用的屏障。他做的事情是:让一组线程到达一个屏障(也可以叫做同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await方法。


import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
class Scratch {
public static void main(String[] args) throws Exception {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{System.out.println("召唤神龙!");});
for (int i = 0; i < 7; i++) {
final int tmp = i;
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " 收集到第: "+tmp+"龙珠");
try{
cyclicBarrier.await();
}catch(InterruptedException e){
e.printStackTrace();
}catch (BrokenBarrierException e){
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
}
}

在这里插入图片描述


Semaphore

Semaphore:信号标、信号量 信号量主要用于两个目的:一个是用于多个共享资源的互斥使用,另一个是用于并发线程数的控制。 【抢车位为例】


import java.util.concurrent.*;
class Scratch {
public static void main(String[] args) throws Exception {
Semaphore semaphore = new Semaphore(3);//只有3个车位
for (int i = 0; i < 6; i++) { //6辆车
final int tmp = i;
new Thread(() -> {
try{
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " 抢到车位");
//暂停一会线程
try{TimeUnit.SECONDS.sleep(3);}catch (InterruptedException e){e.printStackTrace();}
System.out.println(Thread.currentThread().getName() + " 停车3秒后离开车位");
}catch(InterruptedException e){
e.printStackTrace();
}finally {
semaphore.release();
}
}, String.valueOf(i)).start();
}
}
}

在这里插入图片描述


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_36755571/article/details/111246091

随机推荐

SpringCloud微服务创建流程

SpringCloud微服务创建流程

微服务在我们创建好目录结构后,发现我们的项目中出现了很多问题,再次给大家解决一下。比如:项目点击启动无法启动、项目直接互相依赖无法打包、项目如何创建、该打什么...

qq_41498751 阅读(415)

MySQL 架构原理

大家好,欢迎学习本篇文章,探索技术,追求本源。MySQL体系架构接下来介绍的MySQL体系结构,它是属于MySQL架构原理当中的内容࿰...

1737987270 阅读(911)

笔记

笔记

...

杭州小哥哥 阅读(669)

Mysql模糊查询 中的小技巧

第一种:(代码逻辑)不推荐使用if(!"".equals(sysUser.getUserid())&&sysUser.getUserid()!...

一梦春秋。 阅读(703)

SpringBoot03:yaml配置注入

目录 1.yaml语法学习1.1、配置文件1.2、yaml概述1.3、yaml基础语法2.注入配置文件2.1、yaml注入配置文件2.2、加载指定的配置文件2.3、配置文件占位符2.4、回顾prope...

最小的帆也能远航 阅读(718)