CyclicBarrier 基本用法

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模拟所有的数据,每个线程占据一个keyprivate 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() {@Overridepublic 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.

日志说明:

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

源代码地址

  • github
  • gitee

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/76711.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[特殊字符] 手机连接车机热点并使用 `iperf3` 测试网络性能

好的&#xff0c;以下是根据你的描述整理出来的步骤及解释&#xff1a; &#x1f4f6; 手机连接车机热点并使用 iperf3 测试网络性能 本文将通过 iperf3 来测试手机和车机之间的网络连接性能。我们会让车机作为服务端&#xff0c;手机作为客户端&#xff0c;进行 UDP 流量传输…

FPGA上实现SD卡连续多块读的命令

在FPGA上实现SD卡连续多块读的命令 CMD17命令一次只能读取1个块 CMD18命令一次可以连续读取多个块&#xff0c;直到停止命令CMD12 CMD18命令读的块数程序可任意设置 目录 前言 一、SD卡多块读命令CMD18 二、停止读命令CMD12 三、SD卡初始化SD卡连续块读操作的verilog代码 …

DeepSeek 助力 Vue3 开发:打造丝滑的日历(Calendar)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

NSGA-II 多目标优化 —— 理论、案例与交互式 GUI 实现

目录 NSGA-II 多目标优化 —— 理论、案例与交互式 GUI 实现一、引言二、NSGA-II 基本原理2.1 非支配排序2.2 拥挤距离2.3 算法流程三、数学模型与算法推导3.1 多目标优化问题描述3.2 非支配关系与排序3.3 拥挤距离计算四、NSGA-II 的优缺点4.1 优点4.2 缺点五、典型案例分析5.…

库学习04——numpy

一、基本属性 二、 创建数组 &#xff08;一&#xff09;arange a np.arange(10,20,2) # [10,12,14,16,18] 只有一个参数n的话&#xff0c;默认是从0到n-1的一维数组。 &#xff08;二&#xff09;自定义reshape a np.arange(12).reshape((3,4)) [[ 0 1 2 3][ 4 5 …

NVIDIA Jetson 快速切换CUDA版本| 多CUDA版本

当NVIDIA Jetson中安装了多个CUDA时&#xff0c;可以通过命令&#xff0c;快速切换不同版本的。 这样在环境变量和代码编译时&#xff0c;能使用指定版本的CUDA了。 本文适用于Jetson Nano、TX1/TX2、Xavier 和 Orin系列的设备&#xff0c;供大家参考。 cuda参考地址&#xf…

当开源邂逅AI,公益长出翅膀 | 回顾3.30 上海「开源×AI 赋能公益」Meetup

在春和景明的三月&#xff0c;一场打破常规的公益聚会在上海剪爱公益发展中心肇清项目点温暖上演。这&#xff0c;便是G-Star公益行带来的「开源AI 赋能公益」Meetup&#xff0c;一场技术与善意交织、创新与温暖共生的奇妙之旅。 活动现场&#xff0c;没有高冷的技术壁垒&#…

高阶函数/柯里化/纯函数

本篇文章主要是介绍一下标题里面的概念&#xff0c;在面试的时候经常文档&#xff0c;结合阅读到的资料&#xff0c;结合本人的个人见解出品了该文章&#xff0c;如有写的不好的地方或理解有误的&#xff0c;还望阁下多多指教。 1、高阶函数 什么是高阶函数&#xff1f; 接受…

Docker+Jenkins+Gitee自动化项目部署

前置条件 docker安装成功 按照下面配置加速 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-EOF {"registry-mirrors": ["https://register.librax.org"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker一、…

穿梭在数字王国:Python进制转换奇遇记

穿梭在数字王国:Python进制转换奇遇记 想象一下,你是一位勇敢的探险家,正在穿越神秘的"数字王国"。在这个王国里,不同的地区使用着不同的语言(或者说,进制)。二进制村的居民只懂"0"和"1";八进制镇的人们使用0到7的数字;而十六进制城的…

FileInputStream 详解与记忆方法

FileInputStream 详解与记忆方法 一、FileInputStream 核心概念 FileInputStream 是 Java 中用于从文件读取原始字节的类&#xff0c;继承自 InputStream 抽象类。 1. 核心特点 特性说明继承关系InputStream → FileInputStream数据单位字节&#xff08;8bit&#xff09;用…

设计模式 四、行为设计模式(2)

五、状态模式 1、概述 状态设计模式是一种行为型设计模式&#xff0c;它允许对象在其内部状态发生时改变其行为&#xff0c;这种模式可以消除大量的条件语句&#xff0c;并将每个状态的行为封装到单独的类中。 状态模式的主要组成部分如下&#xff1a; 1&#xff09;上…

大模型学习八:‌Sealos 私有化部署之VMware 安装ubuntu22.04 虚拟机安装(实操)

一、说明 windows 11 ubuntu22.04.5 安装5个虚拟机&#xff0c;3个master 2个node 二、安装 Vmware 17&#xff08;没成功&#xff0c;但你可以成功&#xff09; 我的电脑配置比较旧&#xff0c;直接提示处理器不支持xsave 无法打开虚拟机的电源&#xff0c;网上方法试过了…

Win32++ 使用初探

文章目录 1. 环境要求2. Win32安装3. 项目创建3.1 项目创建&#xff08;1&#xff09;直接使用Win32里的示例Sample&#xff08;2&#xff09;自行创建项目 最近想用 VC写些 UI&#xff0c;但又不太想用 MFC&#xff0c;正好对界面要求不太高&#xff0c;就使用了一下 Win3…

R 语言科研绘图第 38 期 --- 饼状图-玫瑰

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…

Linux驱动开发进阶(六)- 多线程与并发

文章目录 1、前言2、进程与线程3、内核线程4、底半步机制4.1、软中断4.2、tasklet4.3、工作队列4.3.1、普通工作项4.3.2、延时工作项4.3.3、工作队列 5、中断线程化6、进程6.1、内核进程6.2、用户空间进程 7、锁机制7.1、原子操作7.2、自旋锁7.3、信号量7.4、互斥锁7.5、comple…

第四节:React Hooks进阶篇-useEffect依赖项为空数组[]与不写的区别

陷阱题&#xff1a;闭包问题、Stale Closure举例 一、依赖项为空数组[]与不写的核心区别 行为空数组[]不写依赖项执行时机仅在组件挂载时执行一次&#xff08;类似componentDidMount&#xff09;组件每次渲染后都执行&#xff08;类似componentDidUpdate&#xff09;更新触发…

【第39节】windows编程:打造MFC版本任务管理器

目录 一、项目概述 二、项目开发的各种功能关键 2.1 进程信息的获取 2.2 线程信息的获取 2.3 进程模块信息的获取 2.3.1 模块快照 2.3.2 枚举模块 2.4 进程堆信息的获取 2.5 窗口信息的获取 2.6 文件信息的获取 2.7 内存信息和CPU占用率的获取 2.7.1 内存信息相关结…

计算轴承|滚动轴承故障频率

一、轴承故障频率概述 在旋转机械故障诊断中&#xff0c;轴承故障频率&#xff08;BPFO、BPFI、BSF、FTF&#xff09;是重要的分析依据。通过计算这些特征频率&#xff0c;可以帮助工程师&#xff1a; 识别轴承故障类型&#xff08;内圈/外圈/滚动体故障&#xff09;制定振动…

【数据结构与算法】ArrayList 和 顺序表

文章目录 &#x1f332;List&#x1f332;1. 线性表&#x1f332;2. 顺序表&#x1f33f;2.1 MyArrayList2.1.1 类中重写所有接口方法1.新增元素2.在pos位置新增元素(指定位置)3.判定是否包含了某个特定元素 4.查找特定元素对应的位置 5.获取pos下标的元素 6.给pos位置的元素替…