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

相关推荐
球king4 分钟前
CC GUI 插件:在 IDEA 中使用 CodeX
java·ide·intellij-idea
cui_ruicheng11 分钟前
Python从入门到实战(八):封装、多态与抽象类
开发语言·python
apihz12 分钟前
台风实时与历史详情查询免费 API 接口完整教程
android·开发语言·tcp/ip·dubbo·台风·天气预报
知无不研26 分钟前
c语言和c++中的静态关键字
开发语言·c++·静态关键字
豆瓣鸡33 分钟前
网关、服务 userId 透传
java·微服务·gateway
bksczm41 分钟前
Linux之信号量(POSIX标准)
java·开发语言
Devin~Y1 小时前
电商场景下的Java面试实战:从Spring Boot微服务到Kafka、Redis与AI RAG
java·spring boot·redis·elasticsearch·spring cloud·微服务·kafka
吠品1 小时前
PHP里取月份最后一天的几种方式
java·开发语言·eureka
CallmeFoureyes1 小时前
使用 C# 提取 Word 文档中的表格数据
开发语言·c#·word
gugucoding1 小时前
2. 【Java】搭建Java开发环境
java·开发语言