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方法释放掉,随后空闲的三个信号量又被其他两个线程拿走(剩下了一个),休眠五秒钟后释放。

相关推荐
05664635 分钟前
Python康复训练——常用标准库
开发语言·python·学习
极光代码工作室35 分钟前
基于SpringBoot的课程预约系统
java·springboot·web开发·后端开发
骊城英雄40 分钟前
基于C#+avalonia ui实现的跨平台点胶机灌胶监控控制上位机软件
开发语言·ui·c#
吾儿良辰1 小时前
一个被BCL遗忘的高性能集合:C# CircularBuffer<T>深度解析
开发语言·windows·c#
昆曲之源_娄江河畔1 小时前
Python如何安装flask, pymssql
开发语言·python·flask·pymssql
Leighteen1 小时前
`try-finally` 里的 `return`:为什么 `finally` 会悄悄改掉返回值、吞掉异常
java·开发语言
0566461 小时前
Python康复训练——控制流与函数
开发语言·python·学习
峥无1 小时前
C++11 深度详解:现代 C++ 基石全梳理
开发语言·c++·笔记
阿米亚波2 小时前
【C++ STL】std::unordered_multimap
开发语言·数据结构·c++·笔记·stl
名字还没想好☜2 小时前
Go 的 time.After 在 select 循环里内存泄漏:定时器堆积原理与 timer.Reset 正确姿势
java·数据库·golang·go·goroutine