CyclicBarrier 基本用法

【JUC】循环屏障CyclicBarrier详解 jdk中提供了许多的并发工具类,大家可能比较熟悉的有,主要用来阻塞一个线程运行,直到其他线程运行完毕。而jdk还有一个功能类似并发工具类,你知道它的作用吗?和有什么区别呢?对于CountDownLatch不了解的可以参考# CountDownLatch源码硬核解析,循环屏障,用来进行线程协作,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,会触发自己运行,运行完后,屏障又会开门,所有被屏障拦截的线程又可以继续运行。所以是可以重用的。 阅读详情

CyclicBarrier 基本用法

简介

CyclicBarrier 是 Java 并发包(java.util.concurrent)中的一个同步辅助类。它允许一组线程相互等待,直到到达某个公共屏障点(common barrier point)。只有当所有参与的线程都到达屏障点时,这些线程才能继续执行。这与CountDownLatch不同,后者是一次性的,而CyclicBarrier可以在等待的线程被释放后重新使用。

使用场景

多线程任务中,让多个线程在某个特定的点上同步,确保完成所有线程都完成某个阶段后,再一起进入下一阶段。

比如:一个计算任务被分成了多个部分,每个部分由不同的线程进行处理,处理完成后需要汇总结果,这时候需要所有线程都完成计算后,才能进行汇总。

基本用法

创建 CyclicBarrier

使用 new CyclicBarrier(int parties) 创建一个新的 CyclicBarrier,其中 parties 参数指定了必须调用 await() 方法以使所有线程都能通过屏障的线程数量。

也可以提供第二个参数,这是一个 Runnable,当最后一个线程到达屏障时会执行这个Runnable,这可以用于在所有线程到达屏障之前执行一些特定的操作。

线程中使用 await() 方法

每个线程在需要等待其他线程的地方调用 await() 方法。该方法会挂起当前线程,直到所有线程都调用了 await() 方法。

如果当前线程不是最后一个到达屏障的线程,await() 将阻塞直到所有线程都到达。如果当前线程是最后一个到达的,则所有线程都会被唤醒继续执行。

重置屏障

可以通过调用 reset() 方法来重置 CyclicBarrier,这将导致所有等待的线程收到一个 BrokenBarrierException 异常,并且屏障计数会被重置为其初始状态。

示例

说明:

使用休眠函数模拟实际业务执行的耗时,使用线程池多线程的执行任务,所有任务完成后,汇总计算结果。

公共代码

给出模拟函数,以及线程池定义等前置条件代码。

package com.ysx.utils.concurrent;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.SecureRandom;
import java.util.Map;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CyclicBarrierTest {

    private static final Logger LOGGER = LoggerFactory.getLogger(CyclicBarrierTest.class);

    // 使用map模拟所有的数据,每个线程占据一个key
    private final Map<Integer, Integer> countMap = new ConcurrentHashMap<>();

    // 核心线程数
    private static final int CORE_POOL_SIZE = 5;

    // 线程池
    private static final ExecutorService THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, CORE_POOL_SIZE * 2,
            10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1000));

    /**
     * 使用一个休眠函数,模拟实际业务的计算,并且等待其他线程的结束
     *
     * @param cyclicBarrier 屏障独显
     * @param index 数据的key,这里用index表示
     */
    private void calculate(CyclicBarrier cyclicBarrier, int index) {
        SecureRandom secureRandom = new SecureRandom();
        // 随机休眠时间,并作为数据值
        int randomSleepSeconds = secureRandom.nextInt(10);
        LOGGER.info("<{}> index: {}, randomSleepSeconds: {}.", Thread.currentThread().getName(), index, randomSleepSeconds);

        // 休眠,模拟线程计算耗时
        try {
            Thread.sleep(randomSleepSeconds * 1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 记录计算结果
        countMap.put(index, randomSleepSeconds);

        // 等待其他线程到达这个点
        LOGGER.info("<{}> index: {}, waiting other thread.", Thread.currentThread().getName(), index);
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (BrokenBarrierException e) {
            throw new RuntimeException(e);
        }
        // 通过了这个屏障
        LOGGER.info("<{}> index: {}, has passed barrier.", Thread.currentThread().getName(), index);

    }

}

场景1 基本用法

任务数量不超过线程池的核心线程数

@Test
@DisplayName("基本用法:任务数量不超过线程池的核心线程数")
public void test1() {
    int taskNum = 3;
    int threadNum = Math.min(CORE_POOL_SIZE, taskNum);
    // 这里 CyclicBarrier 的构造函数的参数 parties 表示需要拦截的线程的数量,示例中有3个子线程,1个主线程
    CyclicBarrier cyclicBarrier = new CyclicBarrier(threadNum + 1);
    for (int i = 0; i < threadNum; i++) {
        final int index = i;
        THREAD_POOL_EXECUTOR.execute(() -> calculate(cyclicBarrier, index));
    }
    try {
        // 等待所有子线程任务执行完成,超时时间为1分钟
        LOGGER.info("waiting all thread.");
        cyclicBarrier.await(1, TimeUnit.MINUTES);

        LOGGER.info("<{}> has passed barrier.", Thread.currentThread().getName());
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    } catch (BrokenBarrierException e) {
        throw new RuntimeException(e);
    } catch (TimeoutException e) {
        throw new RuntimeException(e);
    }
    LOGGER.info("finish calculate.");
    int sum = countMap.values().stream().mapToInt(Integer::intValue).sum();
    LOGGER.info("sum: {}.", sum);
}

运行后日志打印参考:(日志打印忽略时间戳)

[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:105 - waiting all thread.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-3> index: 2, randomSleepSeconds: 7.
[pool-2-thread-1]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-1> index: 0, randomSleepSeconds: 7.
[pool-2-thread-2]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-2> index: 1, randomSleepSeconds: 7.
[pool-2-thread-2]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-2> index: 1, waiting other thread.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-3> index: 2, waiting other thread.
[pool-2-thread-1]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-1> index: 0, waiting other thread.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-3> index: 2, has passed barrier.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:108 - <main> has passed barrier.
[pool-2-thread-1]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-1> index: 0, has passed barrier.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:116 - finish calculate.
[pool-2-thread-2]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-2> index: 1, has passed barrier.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:118 - sum: 21.

日志说明:

  • 有3个任务,分别用3个子线程执行,主线程调用 cyclicBarrier.await(1, TimeUnit.MINUTES);方法,表示等待子线程任务执行完成,之后汇总结果。

场景2 构造函数中指定Runnable

构造函数Runnable的用法:该Runnable优先级高

@Test
@DisplayName("构造函数Runnable的用法:该Runnable优先级高")
public void test2() {
    int taskNum = 3;
    int threadNum = Math.min(CORE_POOL_SIZE, taskNum);
    // 这里 CyclicBarrier 的构造函数的参数 parties 表示需要拦截的线程的数量,示例中有3个子线程,1个主线程
    CyclicBarrier cyclicBarrier = new CyclicBarrier(threadNum + 1, new Runnable() {
        @Override
        public void run() {
            LOGGER.info("<{}> is first priority.", Thread.currentThread().getName());
        }
    });
    for (int i = 0; i < threadNum; i++) {
        final int index = i;
        THREAD_POOL_EXECUTOR.execute(() -> calculate(cyclicBarrier, index));
    }
    try {
        // 等待所有子线程任务执行完成,超时时间为1分钟
        LOGGER.info("waiting all thread.");
        cyclicBarrier.await(1, TimeUnit.MINUTES);

        LOGGER.info("<{}> has passed barrier.", Thread.currentThread().getName());
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    } catch (BrokenBarrierException e) {
        throw new RuntimeException(e);
    } catch (TimeoutException e) {
        throw new RuntimeException(e);
    }
    LOGGER.info("finish calculate.");
    int sum = countMap.values().stream().mapToInt(Integer::intValue).sum();
    LOGGER.info("sum: {}.", sum);
}

打印日志参考:

[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:139 - waiting all thread.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-3> index: 2, randomSleepSeconds: 9.
[pool-2-thread-2]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-2> index: 1, randomSleepSeconds: 7.
[pool-2-thread-1]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-1> index: 0, randomSleepSeconds: 6.
[pool-2-thread-1]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-1> index: 0, waiting other thread.
[pool-2-thread-2]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-2> index: 1, waiting other thread.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-3> index: 2, waiting other thread.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:130 - <pool-2-thread-3> is first priority.
[pool-2-thread-1]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-1> index: 0, has passed barrier.
[pool-2-thread-2]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-2> index: 1, has passed barrier.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-3> index: 2, has passed barrier.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:142 - <main> has passed barrier.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:150 - finish calculate.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:152 - sum: 22.

日志说明:

  • 即构造函数的Runnable的优先级最高,在其他所有到达屏障点之后,这个线程的代码最先执行。

场景3 通用场景:分批处理

使用线程池处理的场景,由于线程池数量是有限的,所以一次并发执行的线程数是有上限的,比如为5,当总任务数为13时,就需要把任务分批处理,以线程池核心线程数量分批,13个任务和分为3批,每个批次分别为5,5,3个任务。在所有批次执行完成之后,再汇总所有的数据。

分批场景需要考虑最后一批的执行,最后一批的数量可能存在小于核心线程数量的情况,要以实际的数量为准。

参考代码如下:

@Test
@DisplayName("通用用法:任务数量存在超过线程池的核心线程数的场景,需要分批处理")
public void test3() {
    int taskNum = 13;
    // 计算分批计算的批次:任务数/核心线程数,并向上取整
    int batchNum = (int) Math.ceil((double) taskNum / CORE_POOL_SIZE);

    for (int batchIndex = 0; batchIndex < batchNum; batchIndex++) {
        int threadNum = CORE_POOL_SIZE;
        if (batchIndex == batchNum - 1) {
            // 如果是最后一批,需要以实际剩余的任务数作为线程数
            threadNum = taskNum - batchIndex * CORE_POOL_SIZE;
        }
        LOGGER.info("batch calculate, batchIndex: {}, threadNum: {}.", batchIndex, threadNum);
        // 这里 CyclicBarrier 的构造函数的参数 parties 表示需要拦截的线程的数量,这里有threadNum个子线程,1个主线程
        CyclicBarrier cyclicBarrier = new CyclicBarrier(threadNum + 1);
        for (int threadIndex = 0; threadIndex < threadNum; threadIndex++) {
            // 当前数据的index需要单独计数
            final int index = threadIndex + batchIndex * CORE_POOL_SIZE;
            THREAD_POOL_EXECUTOR.execute(() -> calculate(cyclicBarrier, index));
        }
        try {
            // 当前批次,等待所有子线程任务执行完成,超时时间为1分钟
            LOGGER.info("waiting all thread in this batch, batchIndex: {}.", batchIndex);
            cyclicBarrier.await(1, TimeUnit.MINUTES);

            LOGGER.info("<{}> has passed barrier in this batch, batchIndex: {}.", Thread.currentThread().getName(), batchIndex);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (BrokenBarrierException e) {
            throw new RuntimeException(e);
        } catch (TimeoutException e) {
            throw new RuntimeException(e);
        }
    }

    LOGGER.info("finish calculate.");
    int sum = countMap.values().stream().mapToInt(Integer::intValue).sum();
    LOGGER.info("sum: {}.", sum);
}

参考日志:

[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:168 - batch calculate, batchIndex: 0, threadNum: 5.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:178 - waiting all thread in this batch, batchIndex: 0.
[pool-2-thread-1]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-1> index: 0, randomSleepSeconds: 3.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-3> index: 2, randomSleepSeconds: 8.
[pool-2-thread-5]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-5> index: 4, randomSleepSeconds: 8.
[pool-2-thread-4]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-4> index: 3, randomSleepSeconds: 8.
[pool-2-thread-2]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-2> index: 1, randomSleepSeconds: 7.
[pool-2-thread-1]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-1> index: 0, waiting other thread.
[pool-2-thread-2]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-2> index: 1, waiting other thread.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-3> index: 2, waiting other thread.
[pool-2-thread-5]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-5> index: 4, waiting other thread.
[pool-2-thread-4]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-4> index: 3, waiting other thread.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:181 - <main> has passed barrier in this batch, batchIndex: 0.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:168 - batch calculate, batchIndex: 1, threadNum: 5.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:178 - waiting all thread in this batch, batchIndex: 1.
[pool-2-thread-1]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-1> index: 0, has passed barrier.
[pool-2-thread-1]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-1> index: 5, randomSleepSeconds: 8.
[pool-2-thread-2]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-2> index: 1, has passed barrier.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-3> index: 2, has passed barrier.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-3> index: 7, randomSleepSeconds: 8.
[pool-2-thread-2]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-2> index: 6, randomSleepSeconds: 8.
[pool-2-thread-5]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-5> index: 4, has passed barrier.
[pool-2-thread-5]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-5> index: 8, randomSleepSeconds: 5.
[pool-2-thread-4]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-4> index: 3, has passed barrier.
[pool-2-thread-4]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-4> index: 9, randomSleepSeconds: 3.
[pool-2-thread-4]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-4> index: 9, waiting other thread.
[pool-2-thread-5]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-5> index: 8, waiting other thread.
[pool-2-thread-2]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-2> index: 6, waiting other thread.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-3> index: 7, waiting other thread.
[pool-2-thread-1]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-1> index: 5, waiting other thread.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:181 - <main> has passed barrier in this batch, batchIndex: 1.
[pool-2-thread-4]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-4> index: 9, has passed barrier.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:168 - batch calculate, batchIndex: 2, threadNum: 3.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:178 - waiting all thread in this batch, batchIndex: 2.
[pool-2-thread-5]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-5> index: 8, has passed barrier.
[pool-2-thread-5]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-5> index: 10, randomSleepSeconds: 2.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-3> index: 7, has passed barrier.
[pool-2-thread-2]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-2> index: 6, has passed barrier.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-3> index: 12, randomSleepSeconds: 5.
[pool-2-thread-4]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:67 - <pool-2-thread-4> index: 11, randomSleepSeconds: 9.
[pool-2-thread-1]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-1> index: 5, has passed barrier.
[pool-2-thread-5]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-5> index: 10, waiting other thread.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-3> index: 12, waiting other thread.
[pool-2-thread-4]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:79 - <pool-2-thread-4> index: 11, waiting other thread.
[pool-2-thread-5]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-5> index: 10, has passed barrier.
[pool-2-thread-3]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-3> index: 12, has passed barrier.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:181 - <main> has passed barrier in this batch, batchIndex: 2.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:191 - finish calculate.
[pool-2-thread-4]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:88 - <pool-2-thread-4> index: 11, has passed barrier.
[main]  INFO  com.ysx.utils.concurrent.CyclicBarrierTest:193 - sum: 82.

日志说明:

  • 分批处理,每个批次内部是并发执行的。
  • 在所有批次执行完成之后,再汇总计算结果。

源代码地址

【高并发】JUC中的循环栅栏CyclicBarrier的6种使用场景 JUC中的循环栅栏CyclicBarrier的6种使用场景。 CyclicBarrier通常称为循环屏障。它和CountDownLatch很相似,都可以使线程先等待然后再执行。不过CountDownLatch是使一批线程等待另一批线程执行完后再执行;而CyclicBarrier只是使等待的线程达到一定数目后再让它们继续执行。故而CyclicBarrier内部也有一个计数器,计数器的初始值在创建对象时通过构造参数指定,如下所示: 。除此之外,CyclicB 阅读详情

相关推荐

并发编程系列之CyclicBarrier用法简介

CyclicBarrier,协同指定数目的线程,让这些线程都在这个屏障前等待,直到所有的线程都到这个屏障前,再一起继续执行。线程执行完成后,这个屏障可以再次使用,因此被称之为循环屏障。

Nicky's blog 1801

CyclicBarrier 使用详解

前言 CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。 CyclicBarrier 默认的构造方法是 CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用 await 方法告诉 CyclicBarrier 我已经到达了屏障,然后当前线程被阻塞。 CyclicBarrier 还提供一个

weixin_39098944的博客 3234

java CountDownLatch、CyclicBarrier和 Semaphore用法

一.CountDownLatch用法   CountDownLatch类位于java.util.concurrent中包下,利用它可以实现类似计数器的功能。比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。   CountDownLatch类只提供了一个构造器: public CountDownLatch(int cou...

gmHappy 6572

CyclicBarrier用法

CountDownLatch和CyclicBarrier CyclicBarrier在用法上其实跟CountDownLatch十分相似,但是前者功能更加强大。 CountDownLatch举例: CountDownLatch countDownLatch=new CountDownLatch(n); 当程序多次执行countDownLatch.countDown();导致计数器n=0时,阻塞的...

长风破浪会有33的博客 1万+

CyclicBarrier的用法

NULL 博文链接:https://hubowei1.iteye.com/blog/2312471

《商用密码应用与安全性评估》第四章密码应用安全性评估实施要点4.1密码应用方案设计

密码应用方案设计

qq_40442137的博客 1471

java中CyclicBarrier的简单用法

CyclicBarrier 和 CountDownLatch 都可以用来让一组线程等待其它线程。与 CyclicBarrier 不同的是,CountdownLatch 不能重新使用。 1 public class TestCyclicBarrier { 2 3 private static final int THREAD_NUM = 5; 4 5 p

sh_c1991的专栏 734

Podman修改镜像源教程(附最新docker镜像源)

Podman修改镜像源教程(附最新docker镜像源)

道长的博客 4141

CyclicBarrier、CountDownLatch、Semaphore 的用法

Semaphore 翻译成字面意思为 信号量,Semaphore 可以控制同时访问的线程个数,通过acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。public boolean tryAcquire(int permits):尝试获取 permits 个许可,若获取成功,则立即返回 true,若获取失败,则立即返回 false。public void acquire(): 用来获取一个许可,若无许可能够获得,则会一直等待,直到获得许可。

qq_24428851的博客 1139

CentOS 7/8 系统下,基于Docker Compose一键部署Dify AI应用平台

本文详细介绍了在CentOS 7/8系统下,使用Docker Compose一键部署Dify AI应用平台的完整流程。从系统环境准备、Docker引擎安装与加速配置,到获取Dify项目、关键环境变量设置,再到服务启动、状态监控及初始化访问,提供了手把手的部署指南和常见问题排查方法,帮助用户快速搭建稳定、可维护的AI应用开发环境。

q5r6s7的博客 139

倍福 MODBUS TCP/IP通信

(*默认字符串80字节,此处声明为255字节,可以一次性传42个UINT数据.5位整数加一个空格,即每个数据6字节*)(*---------------------------------------- 以下为用户程序 ----------------------------------------*)(*读回并换算后的值*)(*准备写到PLC的值*)(*用于比较两次读回的值相差多少,以估计通讯的速度, Act_CalcDiff*)(*用于切换读和写,Act_Protocal*)

qq_33280096的博客 1367

countdowlatch 和 cyclicbarrier的用法以及区别

运动员先准备,裁判喊跑,运动员才开始跑(这是第一次同步,对应begin)。5个人谁跑到终点了,countdown一下,直到5个人全部到达,裁判喊停(这是第二次同步,对应end),然后算时间。定义:是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共的屏障点,所有线程一起继续执行或者返回。用法:用计数 N 初始化CyclicBarrier, 每调用一次await,线程阻塞,并且计数+1(计数起始是0),当计数增长到指定计数N时,所有阻塞线程会被唤醒。但是,只要有一个人没到终点,就不能喝。

2401_87390006的博客 558

Camunda 7.x 系列【67】实战篇之撤销流程

撤销流程 即撤销当前已发起的流程实例。这是一个常见的需求,Camunda本身不提供直接的方法来撤销正在执行的流程,需要自定义处理逻辑。

记录知识、锤炼自我 1377

CyclicBarrier和CountDownLatch的用法与区别

点击关注公众号,实用技术文章及时了解来源:blog.youkuaiyun.com/zyzzxycj/article/details/90241892前言CyclicBarrier和CountDownL...

Java知音 466

【DaVinci Developer专题】-41-APP SWC如何读取写入NVM Block数据

APP SWC Port如何Read读取/Write写入NVM Block数据; DaVinci Developer中的Calibration Parameter/Per-Instance Memory/Service Need如何配置。

「汽车电子助手」的博客 4469

手把手入门YOLO到改进优化教程 | 【P5进阶篇】YOLOv8损失函数改进实战-损失函数IoU之KLD Loss

在本节,将从 KLD Loss(Kullback–Leibler Divergence Loss)的理论到实战代码实现,带你把 KLD Loss融合进 YOLOv8 的训练框架中。并通过训练日志与实验结果,验证 KLD Loss 在实际工程中的优势。

嵌入式阿齐Archie 2万+

CyclicBarrier用法注意

CyclicBarrier用法注意 背景 最近,接运维报,生产环境某个Java应用内存一直缓慢增长。 分析 我们JVM堆内存配置最大和最小是一样,不可能增长;只可能是非堆内存增长。 非堆内存包括类数据、线程、JIT编译的代码、GC数据、常量池、Internal、Compiler等等。 具体参考NMT Memory Categories 通过Spring Boot Admin查看应用详情,发现应用的...

hunger_wang的博客 445

大模型工作流Dify面试题及参考答案

设计一个基于 Dify 的智能摘要与重点提取 Agent,需结合Prompt 工程、模型能力配置和工作流优化,确保对长文本的高效解析和关键信息提炼。1. 明确任务需求与输入输出输入:长文本内容(如文章、报告、会议记录)或文本 URL输出摘要:简洁概括原文核心内容,控制在原文长度的 10%-20%重点列表:分点列出关键数据、结论、行动项等可选:关键词提取、情感倾向分析示例场景输入:一篇 5000 字的行业报告。

大模型大数据攻城狮的专栏 2510

CyclicBarrier 用法详解

CyclicBarrier 用法详解 CyclicBarrier使用场景 用于协调多个线程同步执行操作的场合,所有线程等待完成,然后一起做事情( 相互之间都准备好,然后一起做事情 ) 例如百米赛跑,必须等待所有运动员都准备好了,才能比赛。 运动员准备好,裁判也准备好,才能开始正式比赛。 CyclicBarrier cyclicBarrier = new CyclicBarrier(3); new Thread(() -> { try {

. 8953

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

CyclicBarrier的用法及实例

CyclicBarrier根据官方文档的说明:一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待; 用人的话来说就是:一组线程在并发的执行过程中,设置一个公共点,只有当每个线程都达到这个公共点的时候,所有的线程才会抢占cpu资源继续运行,否则到达公共点的线程都必须得等待; 构...

不要脸的阿智的博客 600

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

CyclicBarrier的基本用法

CyclicBarrier的用法 并行任务的写法 执行结果 张三到达了集合点 李四到达了集合点 王五到达了集合点 ------给你们发门票-------- 王五开始玩喽 李四开始玩喽 张三开始玩喽 具体的代码 CyclicBarrierTest import java.util.concurrent.CyclicBarrier; import java.util.concurr...

maqingbin8888的专栏 185

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

CyclicBarrier 的用法及使用场景

CyclicBarrier : 作用:一个同步辅助工具,它允许一组线程全部进行相互等待彼此到达公共的屏障点后,相互等待的线程会进行并发执行后续的代码逻辑 它同时实现了可循环的屏障操作,并且在屏障释放前可以执行额外的一个操作。 应用场景: 非常适合固定大小的线程的程序中使用,这些线程间或彼此等待。 实际项目场景的应用: 数据的采用多线程的组装 使用方式: 1. 创建好 Cyclic...

u012149894的专栏 1992

java CyclicBarrier的用法

CyclicBarrier:CyclicBarrier的字面意思是可循环(Cyclic) 使用的屏障(barrier).它要做的事情是,让一组线程到达一个屏障(也可以叫做同步点)时被阻塞,知道最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活,线程进入屏障通过CyclicBarrier的await()方法。 场景:假设我们现在有7个人开会,必须要7个人全部到齐才能开始会...

Zhang895341748的专栏 252
上一篇: 常用正则表达式-MAC 地址
下一篇: spring-boot 代码使用DDD结构并使用archunit单元测试看护架构
杨小熊的笔记
博客等级 码龄15年 125粉丝 156原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值