多线程向设备发送数据

需求:做一个部门授权,可以把所选择部门下面的所有人的人脸信息传到设备组里(多个设备),问题在于图片是通过Base64处理之后的,会导致文件名非常长,如果一次性传很多数据就会超过设备的最长请求长度,如果不用Base64处理的话让设备自己去minio下载就会导致特别慢,设备容易掉线,所以就用多线程发送。先看一下全部的代码,再看一下多线程的方法。

全部代码:

@Overridepublic List<Long> createDeptAuthorize(DeptAuthorizeSaveReqVO createReqVO) {List<Long> ids = new ArrayList<>();List<Long> userIds = new ArrayList<>();//遍历部门表,查看该部门是否已有授权List<Long> deptAuthorizeExits = new ArrayList<>();List<Long> deptAuthorizeNotExits = new ArrayList<>();//设备数组List<BaseDeviceDo> baseDeviceDos = new ArrayList<>();//把待更新授权的人员id存在这个数组里List<Long> userUpdateIds = new ArrayList<>();//把待更新授权的人员存在这个数组里List<AdminUserRespDTO> userUpdateList = new ArrayList<>();// 设置用户信息List<User> userList = new ArrayList<>();for (Long l : createReqVO.getDeptId()) {QueryWrapper<DeptAuthorizeDO> queryWrapperDept = new QueryWrapper<>();queryWrapperDept.eq("dept_id", l);queryWrapperDept.eq("deleted", 0);DeptAuthorizeDO deptAuthorizeDO1 = deptAuthorizeMapper.selectOne(queryWrapperDept);if (deptAuthorizeDO1 != null) {//表里存在这条数据就代表已有部门授权,所以要修改部门授权deptAuthorizeExits.add(deptAuthorizeDO1.getDeptId());}else{deptAuthorizeNotExits.add(l);}}//先遍历不存在的部门授权,即新增授权并发到设备上for (Long l : deptAuthorizeNotExits) {// 插入DeptAuthorizeDO deptAuthorize = new DeptAuthorizeDO();deptAuthorize.setDeptId(l);deptAuthorize.setAuthorizeWay(createReqVO.getAuthorizeWay());deptAuthorize.setDoorId(createReqVO.getDoorId());deptAuthorize.setDoorGroupId(createReqVO.getDoorGroupId());deptAuthorize.setEffectMethod(createReqVO.getEffectMethod());deptAuthorize.setInPeriodId(createReqVO.getInPeriodId());deptAuthorize.setOutPeriodId(createReqVO.getOutPeriodId());deptAuthorizeMapper.insert(deptAuthorize);// 假设deptAuthorizeMapper.insert()返回插入记录的IDids.add(deptAuthorize.getId());//查找这个部门下面有多少人List<AdminUserRespDTO> adminUserDOList = adminUserApi.getUserListByDeptId(l);for (AdminUserRespDTO adminUserDO : adminUserDOList) {//遍历人员数组看看是否在授权生效表里QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.eq("user_id", adminUserDO.getId());queryWrapper.eq("deleted", 0);AuthorizeEffectDO authorizeEffectDO = authorizeEffectMapper.selectOne(queryWrapper);if (authorizeEffectDO == null) {//如果不存在就插入这条数据AuthorizeEffectDO authorizeEffectDO1 = new AuthorizeEffectDO();authorizeEffectDO1.setUserId(adminUserDO.getId());//0代表部门授权authorizeEffectDO1.setAuthorizeEffectType(0);//0代表非临时授权authorizeEffectDO1.setIsTemporary(0);authorizeEffectMapper.insert(authorizeEffectDO1);userIds.add(adminUserDO.getId());//插入授权日志(生效表里没有这条数据则代表这人没有授权所以肯定会授权成功)AuthorizeLogDO authorizeLogDO = new AuthorizeLogDO();//授权idauthorizeLogDO.setAuthorizeId(deptAuthorize.getId());//授权类型(0:部门 1:特殊 2:个人 3:临时)authorizeLogDO.setAuthorizeType(0);//用户idauthorizeLogDO.setUserId(adminUserDO.getId());//备注authorizeLogDO.setRemark("创建部门授权成功");//是否成功(0:成功 1:失败)authorizeLogDO.setIsSuccess(0);//插入authorizeLogMapper.insert(authorizeLogDO);} else {//如果不存在这条数据则把生效设置为1//临时>人>特殊>部门if (authorizeEffectDO.getAuthorizeEffectType() != 1 && authorizeEffectDO.getAuthorizeEffectType() != 2) {//0代表部门授权authorizeEffectDO.setAuthorizeEffectType(0);authorizeEffectMapper.updateById(authorizeEffectDO);userIds.add(adminUserDO.getId());//插入授权日志(生效表里没有这条数据则代表这人没有授权所以肯定会授权成功)AuthorizeLogDO authorizeLogDO = new AuthorizeLogDO();//授权idauthorizeLogDO.setAuthorizeId(deptAuthorize.getId());//授权类型(0:部门 1:特殊 2:个人 3:临时)authorizeLogDO.setAuthorizeType(0);//用户idauthorizeLogDO.setUserId(adminUserDO.getId());//备注authorizeLogDO.setRemark("创建部门授权成功");//是否成功(0:成功 1:失败)authorizeLogDO.setIsSuccess(0);//插入authorizeLogMapper.insert(authorizeLogDO);} else {//记录在授权日志里//插入授权日志(失败)AuthorizeLogDO authorizeLogDO = new AuthorizeLogDO();//授权idauthorizeLogDO.setAuthorizeId(deptAuthorize.getId());//授权类型(0:部门 1:特殊 2:个人 3:临时)authorizeLogDO.setAuthorizeType(0);//用户idauthorizeLogDO.setUserId(adminUserDO.getId());//备注authorizeLogDO.setRemark("创建部门授权失败,已有更高授权");//是否成功(0:成功 1:失败)authorizeLogDO.setIsSuccess(1);//插入authorizeLogMapper.insert(authorizeLogDO);}}}List<AdminUserRespDTO> adminUserDOS =adminUserApi.getUserListByDeptId(l);for (AdminUserRespDTO adminUserDO : adminUserDOS) {//更新这个部门下面人的权限//用户列表User user = new User();AdminUserRespDTO user1 = adminUserApi.getUser(adminUserDO.getId());user.setI(user1.getUserSn());user.setN(user1.getNickname());user.setU(user1.getUserSn());user.setC("");user.setB("");user.setW(user1.getPassword());user.setD(user1.getDeptName());//出门规则if (createReqVO.getAuthorizeWay()==0) {//门授权,判断这个门下的设备是进门还是出门List<DoorDeviceRelateRespDTO> doorDeviceRelateList = doorDeviceRelateApi.getDoorDeviceRelateList(createReqVO.getDoorId());for (DoorDeviceRelateRespDTO doorDeviceRelateRespDTO : doorDeviceRelateList) {if (doorDeviceRelateRespDTO != null && doorDeviceRelateRespDTO.getInOutDirection() == 0){//存在并且为进门(0进门 1出门)
//                                Long inPeriodId = accessPeriodMapper.selectById(createReqVO.getInPeriodId()).getParentRuleId();user.setM(createReqVO.getInPeriodId().toString());}else if (doorDeviceRelateRespDTO != null && doorDeviceRelateRespDTO.getInOutDirection() == 1){//存在并且为出门(0进门 1出门)
//                                AccessPeriodDO accessPeriodDO = accessPeriodMapper.selectById(createReqVO.getOutPeriodId());
////                                Long outPeriodId = accessPeriodMapper.selectById(createReqVO.getOutPeriodId()).getParentRuleId();user.setM(createReqVO.getOutPeriodId().toString());}}}else if (createReqVO.getAuthorizeWay() == 1){//获取这个门组下面的门QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.eq("group_id",createReqVO.getDoorGroupId());queryWrapper.eq("deleted",0);List<GroupDoorRelateDO> doorRelateDOS = doorRelateMapper.selectList(queryWrapper);for (GroupDoorRelateDO doorRelateDO : doorRelateDOS) {List<DoorDeviceRelateRespDTO> doorDeviceRelateList = doorDeviceRelateApi.getDoorDeviceRelateList(doorRelateDO.getDoorId());for (DoorDeviceRelateRespDTO doorDeviceRelateRespDTO : doorDeviceRelateList) {if (doorDeviceRelateRespDTO != null && doorDeviceRelateRespDTO.getInOutDirection() == 0){//存在并且为进门(0进门 1出门)user.setM(createReqVO.getOutPeriodId().toString());}else if (doorDeviceRelateRespDTO != null && doorDeviceRelateRespDTO.getInOutDirection() == 1){//存在并且为出门(0进门 1出门)user.setM(createReqVO.getOutPeriodId().toString());}}}}//照片FaceImageRespDTO faceImageDO = faceImageApi.getFaceImage(user1.getId());if (faceImageDO != null) {if (faceImageDO.getImage() != null && !faceImageDO.getImage().isEmpty()) {// minio路径转换为文件路径String objectName = faceImageDO.getImage().split("/")[faceImageDO.getImage().split("/").length - 1];// 从 MinIO 下载文件并转换为字节数组byte[] fileBytes = minioToBase64.downloadFileFromMinio(objectName);// 转换为 Base64 字符串String base6String4 = minioToBase64.convertToBase64(fileBytes);user.setF(base6String4);}}//放到user列表里传给设备userList.add(user);}}//遍历已有部门授权列表,即修改现有的部门授权for (Long deptAuthorizeExit : deptAuthorizeExits) {QueryWrapper queryWrapperDeptAuthorize = new QueryWrapper();queryWrapperDeptAuthorize.eq("dept_id",deptAuthorizeExit);queryWrapperDeptAuthorize.eq("deleted",0);//修改部门授权DeptAuthorizeDO deptAuthorizeDO = deptAuthorizeMapper.selectOne(queryWrapperDeptAuthorize);//更新部门授权列表的基础性徐deptAuthorizeDO.setAuthorizeWay(createReqVO.getAuthorizeWay());deptAuthorizeDO.setDoorId(createReqVO.getDoorId());deptAuthorizeDO.setDoorGroupId(createReqVO.getDoorGroupId());deptAuthorizeDO.setEffectMethod(createReqVO.getEffectMethod());deptAuthorizeDO.setInPeriodId(createReqVO.getInPeriodId());deptAuthorizeDO.setOutPeriodId(createReqVO.getOutPeriodId());deptAuthorizeDO.setUpdateTime(LocalDateTime.now());deptAuthorizeMapper.updateById(deptAuthorizeDO);//查找这个部门下面有多少人List<AdminUserRespDTO> adminUserDOList = adminUserApi.getUserListByDeptId(deptAuthorizeExit);for (AdminUserRespDTO adminUserDO : adminUserDOList) {//遍历人员数组看看是否在授权生效表里有高于部门授权的授权,如果有则不授权QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.eq("user_id", adminUserDO.getId());//目前生效类型为部门授权queryWrapper.eq("authorize_effect_type",0);queryWrapper.eq("deleted",0);AuthorizeEffectDO authorizeEffectDO = authorizeEffectMapper.selectOne(queryWrapper);if (authorizeEffectDO != null) {//把符合规定的人插入到待更新的userId数组中userUpdateIds.add(authorizeEffectDO.getUserId());userUpdateList.add(adminUserApi.getUser(authorizeEffectDO.getUserId()));}}for (AdminUserRespDTO adminUserRespDTO : userUpdateList) {//更新这个部门下面人的权限//用户列表User user = new User();AdminUserRespDTO user1 = adminUserApi.getUser(adminUserRespDTO.getId());user.setI(user1.getUserSn());user.setN(user1.getNickname());user.setU(user1.getUserSn());user.setC("");user.setB("");user.setW(user1.getPassword());user.setD(user1.getDeptName());//出门规则if (createReqVO.getAuthorizeWay()==0) {//门授权,判断这个门下的设备是进门还是出门List<DoorDeviceRelateRespDTO> doorDeviceRelateList = doorDeviceRelateApi.getDoorDeviceRelateList(createReqVO.getDoorId());for (DoorDeviceRelateRespDTO doorDeviceRelateRespDTO : doorDeviceRelateList) {if (doorDeviceRelateRespDTO != null && doorDeviceRelateRespDTO.getInOutDirection() == 0){//存在并且为进门(0进门 1出门)
//                                Long inPeriodId = accessPeriodMapper.selectById(createReqVO.getInPeriodId()).getParentRuleId();user.setM(createReqVO.getInPeriodId().toString());}else if (doorDeviceRelateRespDTO != null && doorDeviceRelateRespDTO.getInOutDirection() == 1){//存在并且为出门(0进门 1出门)
//                                AccessPeriodDO accessPeriodDO = accessPeriodMapper.selectById(createReqVO.getOutPeriodId());
////                                Long outPeriodId = accessPeriodMapper.selectById(createReqVO.getOutPeriodId()).getParentRuleId();user.setM(createReqVO.getOutPeriodId().toString());}}}else if (createReqVO.getAuthorizeWay() == 1){//获取这个门组下面的门QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.eq("group_id",createReqVO.getDoorGroupId());queryWrapper.eq("deleted",0);List<GroupDoorRelateDO> doorRelateDOS = doorRelateMapper.selectList(queryWrapper);for (GroupDoorRelateDO doorRelateDO : doorRelateDOS) {List<DoorDeviceRelateRespDTO> doorDeviceRelateList = doorDeviceRelateApi.getDoorDeviceRelateList(doorRelateDO.getDoorId());for (DoorDeviceRelateRespDTO doorDeviceRelateRespDTO : doorDeviceRelateList) {if (doorDeviceRelateRespDTO != null && doorDeviceRelateRespDTO.getInOutDirection() == 0){//存在并且为进门(0进门 1出门)user.setM(createReqVO.getOutPeriodId().toString());}else if (doorDeviceRelateRespDTO != null && doorDeviceRelateRespDTO.getInOutDirection() == 1){//存在并且为出门(0进门 1出门)user.setM(createReqVO.getOutPeriodId().toString());}}}}//照片FaceImageRespDTO faceImageDO = faceImageApi.getFaceImage(user1.getId());if (faceImageDO != null) {if (faceImageDO.getImage() != null && !faceImageDO.getImage().isEmpty()) {// minio路径转换为文件路径String objectName = faceImageDO.getImage().split("/")[faceImageDO.getImage().split("/").length - 1];// 从 MinIO 下载文件并转换为字节数组byte[] fileBytes = minioToBase64.downloadFileFromMinio(objectName);// 转换为 Base64 字符串String base6String4 = minioToBase64.convertToBase64(fileBytes);user.setF(base6String4);}}//放到user列表里传给设备userList.add(user);}}//判断相关联的门找到要传输的设备if (createReqVO.getAuthorizeWay() == 0){//门授权//获得这个门下面的所有设备List<DoorDeviceRelateRespDTO> doorDeviceRelateList = doorDeviceRelateApi.getDoorDeviceRelateList(createReqVO.getDoorId());for (DoorDeviceRelateRespDTO doorDeviceRelateRespDTO : doorDeviceRelateList) {OnsiteEquipDO onsiteEquipDO = onsiteEquipMapper.selectById(doorDeviceRelateRespDTO.getDeviceId());//插入设备列表BaseDeviceDo baseDeviceDo = new BaseDeviceDo();baseDeviceDo.setDeviceType(onsiteEquipDO.getDeviceModel());baseDeviceDo.setIpAddr(onsiteEquipDO.getDeviceIp());baseDeviceDo.setPassword(onsiteEquipDO.getDevicePassword());baseDeviceDos.add(baseDeviceDo);}}else if (createReqVO.getAuthorizeWay() == 1){//门组授权//获得门组下的所有设备List<OnsiteEquipDO> onsiteEquipDOS = groupDoorRelateService.listByAccessGroupTableId(createReqVO.getDoorGroupId());onsiteEquipDOS.stream().forEach(onsiteEquipDO -> {BaseDeviceDo baseDeviceDo = new BaseDeviceDo();baseDeviceDo.setDeviceType(onsiteEquipDO.getDeviceModel());baseDeviceDo.setIpAddr(onsiteEquipDO.getDeviceIp());baseDeviceDo.setPassword(onsiteEquipDO.getDevicePassword());baseDeviceDos.add(baseDeviceDo);});}// 创建线程池ExecutorService executorService = Executors.newFixedThreadPool(3);// 分批处理用户列表int batchSize = 5;int totalTasks = (userList.size() + batchSize - 1) / batchSize;for (int i = 0; i < totalTasks; i++) {int start = i * batchSize;int end = Math.min(start + batchSize, userList.size());List<User> usersBatch = userList.subList(start, end);executorService.submit(() -> {control.setDeviceUser(baseDeviceDos, usersBatch);});}// 关闭线程池executorService.shutdown();try {// 等待所有任务完成executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);} catch (InterruptedException e) {e.printStackTrace();}return ids;}

多线程方法:

// 创建线程池ExecutorService executorService = Executors.newFixedThreadPool(3);// 分批处理用户列表int batchSize = 5;int totalTasks = (userList.size() + batchSize - 1) / batchSize;for (int i = 0; i < totalTasks; i++) {int start = i * batchSize;int end = Math.min(start + batchSize, userList.size());List<User> usersBatch = userList.subList(start, end);executorService.submit(() -> {control.setDeviceUser(baseDeviceDos, usersBatch);});}// 关闭线程池executorService.shutdown();try {// 等待所有任务完成executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);} catch (InterruptedException e) {e.printStackTrace();}

1. 创建线程池

ExecutorService executorService = Executors.newFixedThreadPool(3);

  • 使用 Executors.newFixedThreadPool(3) 创建了一个固定大小为 3 的线程池。

  • 线程池的作用是管理线程的生命周期,避免频繁创建和销毁线程带来的性能开销。

  • 在这个线程池中,最多可以同时运行 3 个线程。

每次运行三个线程可以解决掉请求头过长的问题。

2. 计算分批处理的批次数量

int batchSize = 5;
int totalTasks = (userList.size() + batchSize - 1) / batchSize;

  • batchSize 定义了每一批次处理的用户数量,这里设置为 5。

  • totalTasks 计算总共需要处理的批次数量。通过公式 (userList.size() + batchSize - 1) / batchSize,确保即使用户数量不能被 batchSize 整除,也能正确计算出需要的批次数量。

3. 分批处理用户列表

for (int i = 0; i < totalTasks; i++) {
int start = i * batchSize;
int end = Math.min(start + batchSize, userList.size());
List<User> usersBatch = userList.subList(start, end);
executorService.submit(() -> {
control.setDeviceUser(baseDeviceDos, usersBatch);
});
}

  • 循环逻辑

    • 外层循环 for (int i = 0; i < totalTasks; i++) 遍历所有批次。

  • 计算每一批次的范围

    • int start = i * batchSize; 计算当前批次的起始索引。

    • int end = Math.min(start + batchSize, userList.size()); 计算当前批次的结束索引,确保不会超出 userList 的范围。

  • 提取当前批次的用户子列表

    • List<User> usersBatch = userList.subList(start, end); 使用 subList 方法从 userList 中提取当前批次的用户子列表。

  • 提交任务到线程池

    • executorService.submit(() -> { control.setDeviceUser(baseDeviceDos, usersBatch); }); 将任务提交到线程池中执行。

    • 每个任务调用 control.setDeviceUser(baseDeviceDos, usersBatch) 方法,处理当前批次的用户。

4. 关闭线程池并等待所有任务完成

executorService.shutdown();
try {
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}

  • 关闭线程池

    • executorService.shutdown(); 调用 shutdown() 方法,表示不再接受新的任务,但会等待已经提交的任务完成。

  • 等待所有任务完成

    • executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); 调用 awaitTermination 方法,等待线程池中的所有任务完成。

    • 这里使用 Long.MAX_VALUETimeUnit.NANOSECONDS,表示等待时间非常长,几乎等同于无限等待。

  • 异常处理

    • 如果线程被中断,会抛出 InterruptedException,捕获并打印堆栈信息。

这样就可以实现多线程向设备发送数据了。

另:附上设备发送数据的方法,也是多线程,可以参考。

/*** 设置设备用户(正式员工、常驻)*/public List<ReturnMessage> setDeviceUser(List<BaseDeviceDo> baseDeviceDos, List<User> list) {List<ReturnMessage> failureMessages = new ArrayList<>();ExecutorService executor = Executors.newFixedThreadPool(baseDeviceDos.size());List<Runnable> tasks = new ArrayList<>();for (BaseDeviceDo baseDeviceDo : baseDeviceDos) {tasks.add(() -> {ReturnMessage returnMessage = null;try {switch (baseDeviceDo.getDeviceType()) {case M7:returnMessage = m7Control.setDeviceUser(baseDeviceDo, list);}if (returnMessage != null && !returnMessage.getCode().equals("0")) {failureMessages.add(returnMessage);}} catch (Exception e) {e.printStackTrace();// 将异常信息封装到 ReturnMessage 中,或者创建一个新的 ReturnMessage 来表示失败returnMessage.setCode("50100");returnMessage.setMsg("处理设备类型 " + baseDeviceDo.getDeviceType() + "设备IP为:" + baseDeviceDo.getIpAddr() + " 时发生异常: " + e.getMessage());failureMessages.add(returnMessage);}});}tasks.forEach(executor::submit);executor.shutdown();while (!executor.isTerminated()) {// 等待所有线程完成}return failureMessages;}

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

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

相关文章

Buck的Loadline和DVS区别和联系

Buck 电路设计中&#xff0c;有两个概念&#xff0c;一个是Load-Line&#xff0c;一个是DVS&#xff0c;它们的含义是什么呢。 Load-Line&#xff08;也称为有源电压定位&#xff0c;AVP&#xff09;是通过调整BUCK电路的输出电压&#xff0c;使其根据负载电流动态变化的技术。…

MySQL会话连接数消耗内存分析

关于连接数消耗内存情况 FROM DEEPSEEK 在 MySQL 中&#xff0c;每个单独的空闲连接所消耗的内存量取决于多个因素&#xff0c;包括连接的线程栈大小&#xff08;由 thread_stack 参数设置&#xff09;和其他每个连接的缓冲区。根据测试结果来看&#xff0c;对于空闲连接的内…

Objective-C实现调节笔记本屏幕亮度(附完整源码)

Objective-C实现调节笔记本屏幕亮度 在macOS上,您可以使用Objective-C来调节笔记本的屏幕亮度。以下是一个简单的示例,演示如何使用CoreGraphics框架来实现这一功能。请确保您的Xcode项目中包含CoreGraphics框架。 完整源码示例 #import <Cocoa/Cocoa.h> #import <…

三十一、【Linux网站服务器】搭建httpd服务器演示个人主页、用户认证、https加密网站配置

httpd服务器功能演示一、安装 HTTPD 服务二、配置个人用户主页1. 启用个人空间功能2. 创建测试用户及网站目录3. 配置 SELinux 权限三、配置用户认证1. 创建密码文件2. 配置目录认证3. 重启服务生效四、配置 SSL 加密网站1. 生成自签名证书2. 配置 SSL 虚拟主机3. 重启服务验证…

把Java程序部署到本地Docker

一&#xff1a;clean && install程序install之后会在target中生成jar包 二&#xff1a;准备三个文件&#xff08;1&#xff09;其中Dockerfile主要起到配置作用&#xff1a;# 基础镜像 FROM openjdk:17-jdk-slim # 作者 MAINTAINER "" # 配置 ENV PAR…

Java学习-------外观模式

在软件开发中&#xff0c;随着系统的不断迭代&#xff0c;模块会越来越多&#xff0c;模块之间的依赖关系也会变得错综复杂。这不仅会增加开发难度&#xff0c;还会让系统的维护和扩展变得棘手。而外观模式就像一位 “前台接待员”&#xff0c;为复杂的系统提供一个简洁统一的接…

Go语言-->变量

Go语言–>变量 在 Go 语言中&#xff0c;定义变量有几种常见的方式。下面是一些常见的语法和用法&#xff1a; 1. 使用 var 关键字定义变量 最常见的方式是使用 var 关键字&#xff0c;后面跟上变量名和类型。你也可以为变量赋初值。 基本格式&#xff1a; var variableName…

分布式链路追踪的实现原理

分布式链路追踪系统的实现涉及多个核心技术环节&#xff0c;下面我将从数据采集、上下文传播、存储分析等维度深入解析其工作原理。 一、核心架构组件 1. 系统组成模块 #mermaid-svg-pDlZY54w2Z0Bp1H1 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-si…

Python爬虫实战:研究micawber库相关技术构建网页采集系统

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上的数据量呈现出爆炸式增长。如何从海量的网页数据中提取有价值的信息,成为了一个重要的研究课题。网络爬虫作为一种自动获取网页内容的技术,为解决这一问题提供了有效的手段。通过网络爬虫,可以快速、高效地采集…

前端框架Vue3(三)——路由和pinia

路由的理解 路由就是一组key-value的对应关系&#xff0c;多个路由&#xff0c;需要经过路由器的管理。 路由-基本切换效果 导航区、展示区请来路由器制定路由的具体规则&#xff08;什么路径&#xff0c;对应着什么组件&#xff09;形成一个一个的路由 【两个注意点】 路由组件…

【go】实现BMI计算小程序与GUI/WEB端实现

好的&#xff0c;下面是用 Go 语言实现的一个简单的 BMI&#xff08;Body Mass Index&#xff0c;身体质量指数&#xff09;计算器&#xff0c;包含中文注释与完整代码&#xff0c;可以直接运行。 一、BMI 计算公式 BMI体重&#xff08;kg&#xff09;身高2&#xff08;m2&…

Windows系统优化命令-记录

闲着无聊&#xff0c;近来电脑有些卡顿&#xff0c;记录一下相关命令。最好的命令还是格式化╮(╯▽╰)╭ 1. 磁盘清理相关命令 cleanmgr - 磁盘清理工具 cleanmgr启动磁盘清理工具&#xff0c;可清理临时文件、回收站等内容 diskpart - 磁盘分区工具 diskpart用于磁盘管理&…

BFCP协议学习

BFCP是为了SIP呼叫中实现presentation的二进制协议。开源库libbfcp 如何协商角色 SIP 消息的SDP中有BFCP 的部分&#xff0c;其中s-only 代表要当服务器角色&#xff0c;c-only 代表要当client角色。confid, userid 都是需要在后续消息中对齐的。 通过port信息可以为后续bfcp…

常用设计模式系列(十七)—命令模式

常用设计模式系列&#xff08;十七&#xff09;—命令模式 第一节、前言 各位老铁好&#xff01; 今天我来跟大家分享对象行为型模式第二章节——《命令模式》&#xff0c;“命令”一词&#xff0c;通俗易懂&#xff0c;我们在生活中经常会发出各种各样的命令&#xff0c;就像你…

【AI绘画】Stable Diffusion 全面指南:安装、版本对比、功能解析与高级应用

引言&#xff1a;Stable Diffusion 概述 在人工智能图像生成领域&#xff0c;商业工具如Midjourney凭借其集成化服务与高质量输出占据市场&#xff0c;而Stable Diffusion&#xff08;简称SD&#xff09;则以开源特性构建了差异化优势。与商业工具依赖云端资源、受限于订阅费用…

kafka使用kraft

window 使用kafka-storage生成生成一个uuid .\kafka-storage.bat random-uuid格式化存储 在这里插入代码片.\kafka-storage.bat format -t 对应的uuid D:\configure\fisher\kafka\config\kraft\server.properties 启动命令 .\kafka-server-start.bat D:\configure\fisher\kafka…

HCIA-Datacom认证笔记:IP路由基础——核心概念与路由分类

网络技术学习中&#xff0c;IP路由是绕不开的核心知识点&#xff0c;对于备考HCIA-Datacom认证的朋友来说&#xff0c;掌握路由基础能为后续学习打下良好基础。今天带朋友们梳理一下IP路由的核心概念、路由表结构及路由分类一、路由核心概念什么是路由&#xff1f; 简单来说&am…

FFmpeg 安装与使用

文章目录1. 环境部署&#xff08;Windows&#xff09;1.1. 安装包下载1.2. 配置环境变量1.3. 验证安装2. FFmpeg 基础使用教程2.1. 常用命令格式2.2. 基础功能示例2.2.1. 视频转码&#xff08;MP4 → MKV&#xff09;2.2.2. 调整分辨率&#xff08;1080p → 480p&#xff09;2.…

Python 数据分析(四):Pandas 进阶

目录 1. 概述2. 缺失项3. 分组聚合4. 数据合并5. 数据可视化 5.1 折线图5.2 条形图5.3 直方图5.4 散点图5.5 饼图 1. 概述 我们在上一篇文章初识 Pandas中已经对 Pandas 作了一些基本介绍&#xff0c;本文我们进一步来学习 Pandas 的一些使用。 2. 缺失项 在现实中我们获…

结构化文本文档的内容抽取与版本重构策略

结构化文本文档的内容抽取与版本重构策略 摘要 本文深入探讨了结构化文本文档处理领域中的两大核心技术——内容抽取与版本重构。文章首先分析了结构化文档的特点及其在现代信息管理中的重要性&#xff0c;随后系统性地介绍了文档内容抽取的技术路线与方法论&#xff0c;包括…