JUC当中的几个计数类

目录

CountDownLatch

原理

CyclicBarrier

Semaphore


CountDownLatch

官方文档解释:CountDownLatch是一种同步辅助工具,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。

CountDownLatch 使用给定的计数进行初始化。await 方法会阻塞,直到当前计数因 countDown() 方法的调用而减至零,此后所有等待的线程被释放,并且任何后续对 await 的调用都会立即返回。这是一次性现象------计数无法重置。如果需要可以重置计数的版本,请考虑使用 CyclicBarrier。

使用示例:

java 复制代码
import java.util.concurrent.CountDownLatch;

public class CountDownLatchTest {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(5);
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "..........");
                countDownLatch.countDown(); //数量减一
            }, String.valueOf(i)).start();
        }
//        countDownLatch.await(); //等待计数器归零, 然后向下执行
        System.out.println("已经全部执行完成");
    }
}

如果不加上await方法的话,线程不会被阻塞,main线程往下执行,输出打印

如果加上了await方法的话,线程会等待计数器归零才会往下执行

原理

countDownLatch.countDown() //数量减一

countDownLatch.await() //等待计数器归零,然后向下执行

每次有线程调用countDown()数量-1,假设计数器变为0,countDownLatch.await()就会被唤醒,继续执行

CyclicBarrier

CyclicBarrier 是一种同步辅助工具,它允许一组线程互相等待,直到所有线程都到达一个共同的屏障点。CyclicBarrier 在涉及固定大小线程组的程序中非常有用,这些线程偶尔需要互相等待。这个屏障被称为"循环的",是因为它可以在等待的线程被释放后重复使用。 CyclicBarrier 支持一个可选的 Runnable 命令,该命令在每个屏障点执行一次------在组中最后一个线程到达屏障之后,但在任何线程被释放之前。这个屏障操作对于在任意线程继续执行之前更新共享状态非常有用。

通俗理解就是加法计数器

使用方法和CountDownLatch类似

java 复制代码
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierTest {

    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> {
            System.out.println("达到5了.............");
        });

        //创建5个线程
        for (int i = 1; i <= 5; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName());
                try {
                    cyclicBarrier.await(); // 等待
                } catch (InterruptedException | BrokenBarrierException e) {
                    throw new RuntimeException(e);
                }
            }, "Thread-" + i).start();
        }
    }
}

代码创建了一个CyclicBarrier屏障类,它会阻塞到达屏障的线程,然后在构造器里面传入了参数5,表示五个线程到达屏障之后就会释放所有线程,并且传入了一个Runnable线程打印结果

Semaphore

Semaphore 是一个计数信号量。从概念上讲,信号量维护着一组许可。每个 acquire() 方法在必要时会阻塞,直到有可用的许可,然后获取该许可。每个 release() 方法会添加一个许可,可能会释放一个正在阻塞的获取者。但是,并没有实际的许可对象被使用;Semaphore 只是维护可用数量的计数并相应地执行操作。

使用方法

java 复制代码
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class SemaphoreTest {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3); //允许3个线程同时拥有资源
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire(); // 线程得到信号量
                    System.out.println(Thread.currentThread().getName() + "得到信号量......");
                    TimeUnit.SECONDS.sleep(5); //休眠两秒钟
                    System.out.println(Thread.currentThread().getName() + "释放信号量......");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }finally {
                    semaphore.release(); //释放信号量
                }
            }, String.valueOf(i)).start();
        }
    }
}

代码解释:

首先是某三个线程得到信号量,然后是休眠五秒钟后,执行finally代码块里面的release方法释放掉,随后空闲的三个信号量又被其他两个线程拿走(剩下了一个),休眠五秒钟后释放。

相关推荐
朝朝辞暮i8 分钟前
C++ 第 15 课:指针 * 和地址 &
开发语言·c++
蜗牛互联网9 分钟前
GPT-6.1 Sol迁移指南:从token单价转向每任务成本门禁
java·人工智能·后端·gpt
奶茶树11 分钟前
【C++】14. C++11新特性【下】
开发语言·c++
web打印社区13 分钟前
汽修 / 4S 店:维修工单、结算单网页怎么静默出纸
开发语言·前端·javascript·chrome·ecmascript
蜗牛互联网15 分钟前
HSTU在Dynamo-Triton中的AOTI与KV缓存验收方法
java·人工智能·后端·缓存
Sirens.16 分钟前
Java多线程实例:单例模式、阻塞队列、线程池与定时器
java·开发语言·单例模式
青山木18 分钟前
秒杀系统设计(一):需求拆解与流量治理
java·数据库·redis·后端·架构
卓怡学长28 分钟前
w195基于ssm“Fitfrend”个性化健身
java·intellij-idea
沫璃染墨31 分钟前
《从零入门Linux系统篇(五十三):线程篇·六——线程互斥详解:从并发问题到mutex互斥锁》
linux·运维·服务器·开发语言·后端·架构·系统架构
老王爱玩车35 分钟前
深入理解指针6
c语言·开发语言·学习