当前位置: 首页 > news >正文

Linux网络编程day7 线程池and UDP

线程池

typedef struct{void*(*function)(void*);        //函数指针,回调函数void*arg;                       //上面函数的参数
}threadpool_task_t;                 //各子线程任务的结构体/*描述线程池相关信息*/struct threadpool_t{pthread_mutex_t lock;           // 用于锁住本结构体pthread_mutex_t thread_counter; //记录忙状态线程个数的锁 -- bust_thr_numpthread_cond_t queue_not_full;  //当任务队列满时 , 添加任务的线程阻塞 , 等待此条件变量pthread_cond_t queue_not_empty; //任务队列不为空时,通知等待任务的线程pthread_t *threads;             //存放线程池中每个线程的Tid . 数组pthread_t adjust_tid;           //存管理线程的tidthreadpool_task_t *task_queue;  //任务队列--数组首地址int min_thr_num;                //线程池最小线程数int max_thr_num;                //线程池最大线程数int live_thr_num;               //当前存活线程个数int busy_thr_num;               //忙状态线程个数int wait_exit_thr_num;          //要销毁的线程个数int queue_front;                //task_queue队头下标int queue_rear;                 //task_queue队尾下标int queue_size;                 //task_queue队中实际任务数int queue_max_size;             //task_queue队列可容纳任务数上限int shutdown;                   //标志位,线程池使用状态,true or false
};

线程池模块分析

1、main():创建线程池

                   向线程池中添加任务,借助回调处理任务

                   销毁线程池

int main(void)
{//threadpool_t * threadpool_create(int min_thr_num , int max_thr_num , int queue_max_size);threadpool_t *thp = threadpool_create(3 , 100 , 100);//创建线程池,最大数量100,最小数量3 ,任务队列最
大容量100.printf("pool inited");int num[20] , i;  //模拟客户端向服务器发送数据等场景for(i = 0; i < 20 ; i++){num[i] = i;printf("add task %d\n" , i);//int threadpool_add(threadpool_t *pool , void*(*function)(void*arg) , void arg);threadpool_add(thp , process , (void*)&num[i]); //向线程池中添加任务}sleep(10);  //等待子线程完成任务threadpool_destroy(thp);return 0 ;
}

2、pthreadpool_create:创建线程池结构体指针

                                        初始化线程池结构体中N个成员变量

                                        创建N个任务线程

                                        创建1个管理者线程

                                        失败时 , 释放空间

threadpool_t* threadpool_create(int min_thr_num , int max_thr_num , int queue_max_size)
{int i ;struct threadpool_t *pool = NULL; // 线程池 结构体do{if((pool = (struct threadpool_t*)malloc(sizeof(struct threadpool_t))) == NULL){printf("malloc threadpool fail");break;}pool->min_thr_num = min_thr_num;pool->max_thr_num = max_thr_num;pool->busy_thr_num = 0;pool->live_thr_num = min_thr_num; //活着的线程数 初值=最小线程数pool->wait_exit_thr_num = 0;pool->queue_size = 0; //有0个产品pool->queue_max_size = queue_max_size;//最大任务队列数pool->queue_front = 0;pool->queue_rear = 0;pool->shutdown = false; // 不关闭线程池/*根据最大线程上线数 , 给工作线程数组开辟空间,清零*/pool->threads = (pthread*)malloc(sizeof(pthread_t)*max_thr_num);if(pool->threads == NULL){printf("malloc threads fail");break;}memset(pool->threads , 0 , sizeof(pthread_t)*max_thr_num);/*给任务队列开辟空间 */pool->task_queue = (threadpool_task_t*)malloc(sizeof(threadpool_task_t)*queue_max_size);if(pool->task_queue == NULL){printf("malloc task_queue fail");break;}/*初始化互斥锁、条件变量 , 使用init动态初始化 , 加上进行返回值判断*/if(pthread_mutex_init((&pool->lock) , NULL) != 0|| pthread_mutex_init(&(pool->thread_counter) , NULL) != 0|| pthread_cond_init(&(pool->queue_not_empty) , NULL) != 0|| pthread_cond_init(&(pool->queue_not_full) , NULL) != 0){printf("init the lock or cond fail");break;}/*启动min_thr_num个work thread*/for(i = 0 ; i < min_thr_num ; i++){pthread_create(&(pool->threads[i]) , NULL , threadpool_thread , (void*)pool);//pool指向当前线>程池printf("stat thread 0x%x...\n" , (unsigned int)pool->threads[i]);}pthread_create(&(pool->adjust_tid) , NULL , adjust_thread , (void*)pool);//创建管理者线程return pool;}while(0);threadpool_free(pool); // 前面代码调用失败时,释放pool空间return NULL;
}

3、threadpool_thread():进入子线程回调函数。

                                         接收参数(void*)arg

                                         加锁--》lock--》整个结构体的锁

                                         判断条件变量--》wait

/* 线程池中各个工作线程 */
void* threadpool_thread(void* threadpool)
{struct threadpool_t *pool = (struct threadpool_t*)threadpool;threadpool_task_t task;//任务队列对象while(true){/*刚创建出线程,等待任务队列里面有队列 ,否则阻塞等待任务队列李有任务后再唤醒接收任务*/pthread_mutex_lock(&(pool->lock));//queue_size = 0说明没有任务,调用wait函数阻塞在条件变量上,若有任务,跳过whilewhile((pool->queue_size == 0) && (!pool->shutdown)){printf("thread 0x%x is waiting\n" , (unsigned int)pthread_self());pthread_cond_wait(&(pool->queue_not_empty) , &(pool->lock));//清除指定数目的空闲线程,如果要结束的线程个数大于0,结束线程if(pool->wait_exit_thr_num > 0 ){pool->wait_exit_thr_num--;//如果线程池里线程个数大于最小值时可以结束当前线程if(pool->live_thr_num > pool->min_thr_num){printf("thread 0x%x is exiting\n" , (unsigned int)pthread_self());pool_live_thr_num--;pthread_mutex_unlock(&(pool->lock));pthread_exit(NULL);}}//指定true,要关闭线程池里的每个线程,自行退出-->销毁线程池if(pool->shutdown){pthread_mutex_unlock(&(pool->lock));printf("thread 0x%x is exiting\n" , (unsigned int)pthread_self());pthread_detach(pthread_self());pthread_exit(NULL); // 线程自行结束}//从任务队列获取任务,出队操作task.function = pool->task_queue[pool->queue_front].function;task.arg = pool->task_queue[pool->queue_front].arg;pool->queue_front = (pool->queue_front + 1) % pool->queue_max_size; //出队,模拟环形pool->queue_size--;//通知可以有新的任务添加进来pthread_cond_broadcast(&(pool->queue_not_full));//任务取出后立即将线程池锁释放pthread_mutex_unlock(&(pool->lock));//执行任务printf("thread 0x%x stat working\n" , (unsigned int)pthread_self());pthread_mutex_lock(&(pool->thread_counter));    //忙状态线程数变量锁pool->busy_thr_num++;                           //忙状态线程数+1pthread_mutex_unlock(&((pool->thread_counter));(*(task.function))(task.arg);//执行回调函数//任务结束处理printf("thread 0x%x end working\n" , (unsigned int)pthread_self());pthread_mutex_lock(&(pool->thread_counter));pool->busy_thr_num--;                           //处理掉任务,忙状态线程数-1pthread_mutex_unlock(&(pool->thread_counter));}pthread_exit(NULL);
}

4、adjust_thread():进入管理者线程回调函数                                 

                                 循环10s执行一次

                                 接收参数(void*)arg

                                 加锁--》lock--》整个结构体的锁

                                 获取管理线程时需要用到的变量:live busy queue task

                                 根据既定算法,使用上述3变量判断是否应该创建、销毁线程池中的指定步长的线程。

void* adjust_thread(void* threadpool)
{int i ;struct threadpool_t *pool = (struct threadpool_t*)threadpool;while(!pool->shutdown){sleep(DEFAULT_TIME); //定时对线程池管理pthread_mutex_lock(&(pool->lock));int queue_size = pool->queue_size;int live_thr_num  = pool->live_thr_num;pthread_mutex_unlock(&(pool->lock));pthread_mutex_lock(&(pool->thread_counter));int busy_thr_num = pool->busy_thr_num;pthread_mutex_unlock(&(pool->pthread_counter));//创建新线程,任务数大于最小线程池个数,且存活线程数少于最大线程数if(queue_size >= MIN_WAIT_TASK_NUM && live_thr_num < pool->max_thr_num){pthread_mutex_lock(&(pool->lock));int add = 0;//一次增加DEFAULT_THREAD个线程for(i = 0 ; i < pool->max_thr_num && add < DEFAULT_THREAD_VARY&& pool->live_thr_num < pool_max_thr_num ; i++){pthread_create(&(pool->thread[i]) , NULL , threadpool_thread , (void*)pool);add++;pool->live_thr_num++;}pthread_mutex_unlock(&(pool->lock));}if((busy_thr_num *2) < live_thr_num && live_thr_num > pool->min_thr_num){pthread_mutex_lock(&(pool->lock));pool->wait_exit_thr_num = DEFAULT_THREAD_VARY;pthread_mutex_unlock(&(pool->lock));for(i = 0 ; i < DEFAULT_THREAD_VARY ; i++){pthread_cond_signal(&(pool->queue_not_empty));}}}return NULL;
}

5、threadpool_add:模拟产生任务 num[20]

                                  设置回调函数,处理任务sleep(1)代表处理完成

                                  初始化任务队列结构体成员 回调函数和arg

                                  利用环形队列机制实现添加任务,借助队尾指针

                                  唤醒阻塞在条件变量上的线程

//线程池中的线程,模拟处理业务
void* process(void*arg)
{printf("thread 0x%x working on task %d\n" , (unsigned int)pthread_self() , (int)arg);sleep(1);printf("task %d is end\n" , (int)arg);return NULL
}
int threadpool_add(struct threadpool_t *pool , (void*)(**function)(void*arg) , (void*)arg)
{pthread_mutex_lock(&(pool->lock));//为真 , 队列已满 , 调用wait阻塞while((pool->queue_size == pool->queue_max_size) && (!pool->shutdown)){pthread_cond_wait(&(pool->queue_not_full) , &(pool->lock));}if(pool->shutdown){pthread_cond_broadcast(&(pool->queue_not_empty));pthread_mutex_unlock(&(pool->lock));return 0 ;}//清空工作线程 调用的回调函数 的参数if(pool->task_queue[pool->queue_rear].arg != NULL){pool->task_queue[pool->queue_rear].arg = NULL;}//添加任务到任务队列pool->task_queue[pool->queue_rear].function = function;pool->task_queue[pool->queue_rear].arg = arg;pool->queue_rear = (pool->queue_rear + 1) % pool->queue_max_size;//队尾指针移动,模拟环形pool->queue_size++;//向任务队列中添加一个任务//添加完任务后,队列不为空,唤醒线程池中等待处理任务的线程pthread_cond_signal(&(pool->queue_not_empty));pthread_mutex_unlock(&(pool->lock));return 0 ;
}

6、从3中wait之后执行,处理任务:获取任务处理回调函数及参数

                        利用环形队列机制实现处理任务,借助队头指针

                        唤醒阻塞在条件变量上的server

                        修改忙线程数量++

                        执行处理任务线程

                        修改忙线程数量--

7、创建和销毁线程:管理者线程根据上述三个参数判断是否创建、销毁

                                   满足创建条件pthread_create()回调任务线程函数

                                   满足销毁条件wait_exit_thr_num赋值,signal给阻塞在条件变量上的线程发送假条件满足信号,跳转至wait阻塞,阻塞线程会被假信号唤醒,使用pthread_exit。

int threadpool_destroy(threadpool_t *pool)
{int i;if(pool == NULL)return -1;pool->shutdown = true;pthread_join(pool->adjust_tid , NULL);for(i = 0 ; i < pool->live_thr_num ; i++){pthread_cond_broadcast(&(pool->queue_not_empty));}for(i = 0; i < pool->live_thr_num ; i++){pthread_join(pool->threads[i] , NULL);}threadpool_free(pool);return 0;
}
int threadpool_free(threadpool_t *pool)
{if(pool == NULL)return -1;if(pool->task_queue)free(pool->tast_queue);if(pool->threads){free(pool->threads);pthread_mutex_lock(&(pool->lock));pthread_mutex_destroy(&(pool->lock));pthread_mutex_lock(&(pool->thread_counter));pthread_mutex_destroy(&(pool->thread_counter));pthread_cond_destroy(&(pool->queue_not_full));pthread_cond_destroy(&(pool->queue_not_empty));}free(pool);pool = NULL;return 0;
}

UDP服务器

TCP通信和UDP通信的优缺点

TCP

面向连接的,可靠数据包传输。对于不稳定的网络层,采取完全弥补的通信方式,丢包重传。

优点:稳定 数据流量稳定、速度稳定、顺序

缺点:传输速度慢、效率低,资源开销大。

使用场景:数据完整要求性较高,不追求效率

                  大数据传输、文件传输。

UDP

无连接的,不可靠的数据报传递。对于不稳定的网络层,采取完全不弥补的通信方式,默认还原网络状况。

优点:传输速度快,效率高,资源开销小。

缺点:不稳定 数据流量、速度不稳定,顺序不稳定

使用场景:对时效性要求较高场合。稳定性其次。

                  游戏、视频会议、视频电话。     

----腾讯、华为、阿里 -- 应用层添加数据校验协议,弥补UDP的不足

UDP实现的C/S模型

无三次握手建立连接,故没有accept()、connect()

recv()/send()只能用于TCP通信

server

server:
lfd = socket(AF_INET , SOCK_DGRAM , 0);   SOCK_DGRAM--->报式协议
bind();
listen(); ----可有可无
while(1){  //不使用read函数recvfrom() //涵盖accept函数中的传出地址结构sendto();
}
close();

client

cfd = socket(AF_INET , SOCK_DGRAM , 0);sendto("服务器地址结构" , 地址结构大小)recvfrom()
写屏幕
close()

recvfrom函数

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
socket:lfd
buf:缓冲区地址
len:缓冲区大小
flags:0
src_addr:传出参数,传出对端地址结构
src_addr:传入传出返回值:成功接收数据字节数
失败-1 errno   0对端关闭

sendto函数                 

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
socket:套接字
buf:存储数据的缓冲区
len:数据长度
flags:0
dest_addr:传入参数,目标地址结构
src_addr:地址结构长度返回值:成功写出数据字节数
失败-1 errno   

udp server端模型

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<ctype.h>
#define SERV_PORT 9004
void sys_err(char*s)
{perror(s);exit(1);
}int main(int argc , char*argv[])
{int sockfd , i , n;char buf[BUFSIZ] , str[INET_ADDRSTRLEN];struct sockaddr_in serv_addr , clit_addr;socklen_t clitlen;bzero(&serv_addr , sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(SERV_PORT);serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);sockfd  = socket(AF_INET , SOCK_DGRAM , 0);if(sockfd == -1)sys_err("socket error");bind(sockfd , (struct sockaddr*)&serv_addr , sizeof(serv_addr));printf("Accepting connections-----");while(1){clitlen = sizeof(clit_addr);n = recvfrom(sockfd , buf , strlen(buf) , 0 , (struct sockaddr*)clit_addr, &clitlen);if(n == -1)sys_err("recvfrom error");printf("received from %s at port%d\n" , inet_ntop(AF_INET , &clit_addr.sin_addr , str , sizeof(str)),ntohs(clit_addr.sin_port));for(i = 0 ; i < n ; i++)buf[i] = toupper(buf[i]);n = sendto(sockfd , buf , n , 0 , (struct sockaddr*)&clit_addr , sizeof(clit_addr));if(n == -1)sys_err("sendto error");}close(sockfd);return 0 ;
}

udp client端模型

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<ctype.h>
#define SERV_PORT 9004void sys_err(char*s)
{perror(s);exit(1);
}int main(int argc , char*argv[])
{int sockfd , i , n;char buf[BUFSIZ] ;struct sockaddr_in serv_addr;bzero(&serv_addr , sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(SERV_PORT);inet_pton(AF_INET , "xx.xx.x.xxx" , &serv_addr.sin_addr.s_addr);sockfd  = socket(AF_INET , SOCK_DGRAM , 0);if(sockfd == -1)sys_err("socket error");while((fgets = (buf , BUFSIZ , stdin)) != NULL){n = sendto(sockfd , buf , strlen(buf) , 0 ,(struct sockaddr*)&serv_addr , sizeof(serv_addr));if(n == -1)sys_err("sendto error");n = recvfrom(sockfd , buf , BUFSIZ , 0 , NULL , 0);if(n == -1)sys_err("recvfrom error"); write(STDOUT_FILENO , buf , n); }close(sockfd);return 0 ;
}

相关文章:

Linux网络编程day7 线程池and UDP

线程池 typedef struct{void*(*function)(void*); //函数指针&#xff0c;回调函数void*arg; //上面函数的参数 }threadpool_task_t; //各子线程任务的结构体/*描述线程池相关信息*/struct threadpool_t{pthread_mutex_t lock; …...

WHAT - ahooks vs swr 请求

文章目录 ahooks特点常用 Hooks 示例1. useRequest — 封装网络请求逻辑&#xff08;比 SWR / React Query 更轻量&#xff09;2. useDebounce — 防抖值3. useLocalStorageState — 本地存储的状态4. useBoolean — 快速管理布尔状态5. useEventListener — 添加事件监听 ahoo…...

算法训练营第十一天|150. 逆波兰表达式求值、239. 滑动窗口最大值、347.前 K 个高频元素

150. 逆波兰表达式求值 题目 思路与解法 第一思路&#xff1a; 比较简单 class Solution:def evalRPN(self, tokens: List[str]) -> int:stack []for item in tokens:if item ! and item ! - and item ! * and item ! / :stack.append(item)else:b int(stack.pop())a …...

可视化图解算法35:在二叉树中找到两个节点的最近公共祖先(二叉树的最近公共祖先)

1. 题目 描述 给定一棵二叉树(保证非空)以及这棵树上的两个节点对应的val值 o1 和 o2&#xff0c;请找到 o1 和 o2 的最近公共祖先节点。 数据范围&#xff1a;树上节点数满足 1≤n≤105 , 节点值val满足区间 [0,n) 要求&#xff1a;时间复杂度 O(n) 注&#xff1a;本题保…...

如果说开启的TIM3定时器有ccr1,ccr2,ccr3,我想要关闭ccr2的PWM输出,怎么通过代码实现

目录 作用概述&#xff1a; 具体原理&#xff1a; 代码的操作细节&#xff1a; 实际效果&#xff1a; 示意全文&#xff1a; 小结&#xff1a; TIM3->CCER & ~TIM_CCER_CC2E; 作用概述&#xff1a; 作用是禁用 TIM3 的通道 2&#xff08;CCR2&#xff09;的捕获…...

高能数造全固态电池干法电极高品质原纤化技术:驱动干法和全固态电池制造新进程

技术背景 传统湿法电极制备工艺的局限:传统的湿法电极制备工艺需要使用大量的溶剂来溶解粘结剂和分散活性物质&#xff0c;后续还需要复杂的干燥工序来去除溶剂。这不仅增加了生产成本和能源消耗&#xff0c;溶剂的使用和处理还会带来环境污染和安全隐患。 新能源产业发展的需…...

AI驱动的制造工艺:系统化探索与创新

DeepSeek 技术全景 在当今 AI 技术蓬勃发展的时代,DeepSeek 已成为该领域中一颗耀眼的明星。自 2023 年 7 月 17 日成立以来,这家由知名私募巨头幻方量化孕育而生的公司,迅速在 AI 领域崭露头角 。DeepSeek 的目标是开发顶尖的大语言模型(LLM),并利用数据蒸馏技术打造更精…...

Mac 平台获取地区标识符号

以下是添加了详细中文注释的代码版本&#xff0c;解释每一行代码的作用&#xff1a; #include <CoreFoundation/CoreFoundation.h> #include <vector> #include <string> #include <iostream>// 将 Core Foundation 的字符串(CFStringRef)转换为标准 …...

PyTorch 实战:从 0 开始搭建 Transformer

导入必要的库 python import math import torch import torch.nn as nn from LabmL_helpers.module import Module from labml_n.utils import clone_module_List from typing import Optional, List from torch.utils.data import DataLoader, TensorDataset from torch imp…...

Java 显式锁与 Condition 的使用详解

Java 显式锁与 Condition 的使用详解 在多线程编程中&#xff0c;线程间的协作与同步是核心问题。Java 提供了多种机制来实现线程同步&#xff0c;除了传统的 synchronized 关键字外&#xff0c;ReentrantLock 和 Condition 是更灵活且功能强大的替代方案。本文将详细介绍显式…...

【MySQL】存储引擎 - CSV详解

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…...

LeetCode算法题(Go语言实现)_62

题目 有两种形状的瓷砖&#xff1a;一种是 2 x 1 的多米诺形&#xff0c;另一种是形如 “L” 的托米诺形。两种形状都可以旋转。 给定整数 n &#xff0c;返回可以平铺 2 x n 的面板的方法的数量。返回对 109 7 取模 的值。 平铺指的是每个正方形都必须有瓷砖覆盖。两个平铺不…...

矿井设备通信破局:ModbusTCP转DeviceNet网关应用实践

矿井设备通信破局&#xff1a;ModbusTCP转DeviceNet网关应用实践 在500米深的金属矿井中&#xff0c;传统人工操控采掘设备存在高风险、低效率问题。某矿业集团引入海希无线遥控器远程控制掘进机&#xff0c;却因通信协议冲突陷入困局&#xff1a;海希遥控器采用DeviceNet协议…...

GrassRoot备份项目

Windows服务项目 Grass.cs using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http.Headers; using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Time…...

多级路由器如何避免IP冲突

在多级路由器架构中&#xff0c;避免IP冲突的核心在于合理规划子网、正确配置路由器角色与功能。以下是综合多个搜索结果的解决方案及操作步骤&#xff1a; 一、划分不同子网段 修改LAN口IP地址 主路由器默认LAN口IP为192.168.1.1&#xff0c;次级路由器需更改为不同网段&#…...

VGGNet详解

VGGNet 由牛津大学视觉几何组&#xff08;Visual Geometry Group&#xff09;在2014年提出&#xff0c;凭借极简的 33卷积核堆叠设计 成为经典模型&#xff0c;影响了后续大量网络架构。 1. 网络结构 VGGNet 的核心思想是 通过多层小卷积核&#xff08;33&#xff09;替代大卷…...

TDengine 在新能源行业应用

简介 在当前可再生能源迅速发展的浪潮中&#xff0c;分布式光伏和可再生能源的装机容量已经达到相当可观的规模。尽管新能源的发展得到政策的鼎力扶持&#xff0c;但其并网后对电网的运行调度、供电可靠性以及系统的安全稳定带来诸多新挑战。 分布式光伏&#xff0c;即分布式…...

[人机交互]设计,原型建立和构造

一.建立和构造原型 1.1理解用户需要和技术之间的关系 用户需要和技术之间是一个鸡和蛋的问题 • 用户对产品的理解建立在 与该产品交互 的基础上 • 用户只有在熟悉后&#xff0c;才能 评价 是否需要&#xff0c;及 进一步 的需要 • 构造最终产品需要大量资源 • 原型化 是 …...

C#生成二维码和条形码

C# 实现二维码和条形码生成&#xff1a;从入门到实战 文章目录 C# 实现二维码和条形码生成&#xff1a;从入门到实战一、引言二、准备工作2.1 开发环境搭建2.2 引入相关库 三、生成条形码3.1 条形码基本概念3.2 使用[ZXing.Net](https://ZXing.Net)生成条形码3.2.1 核心代码实现…...

2025.5.8总结(中期审视)

今日记录&#xff1a; 晚上&#xff0c;主管找我聊了关于中期绩效审视的问题。 首先就是让我汇报上半年的工作进展&#xff0c;汇报完后&#xff0c;感觉体现不出自己的工作量&#xff0c;这确实考验个人的汇报能力。 汇报完工作后&#xff0c;主管开始给我提了一些建设性的…...

Pyinstaller编译EXE及反编译

文章目录 适用范围示例文件编译EXE反编译EXE准备工具编译pycdc反编译 反编译得到的文件相关资源下载 适用范围 实测 python3.9可以反编译。从pycdc源代码看&#xff0c;似乎支持到python 3.13。 示例文件 demo.py import sys from PyQt5 import QtWidgets, QtCore, QtGui c…...

3.2.3 掌握RDD转换算子 - 3. 扁平映射算子 - flatMap()

在本节课中&#xff0c;我们深入学习了Spark RDD的flatMap()算子。flatMap()与map()类似&#xff0c;但每个元素可以返回0到多个元素&#xff0c;最终将所有结果合并为一个RDD。通过案例演示&#xff0c;我们首先对单词文件进行了统计&#xff0c;通过map()将每行文本转换为单词…...

深入解析 C# 常用数据结构:特点、区别与优缺点分析

在软件开发中&#xff0c;选择合适的数据结构是提高代码效率和性能的关键。在 C# 中&#xff0c;我们常用的数据结构包括 List、Array、Dictionary<TKey, TValue>、HashSet、Queue、Stack 和 LinkedList。每种数据结构有不同的特点、优缺点和适用场景。本文将结合代码&am…...

LeetCode第284题 - 窥视迭代器

题目 解答一 package leetcode.editor.cn; //leetcode submit region begin(Prohibit modification and deletion) // Java Iterator interface reference: // https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.htmlimport java.util.Iterator; import java.ut…...

克里金模型+多目标优化+多属性决策!Kriging+NSGAII+熵权TOPSIS!

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 克里金模型多目标优化多属性决策&#xff01;KrigingNSGAII熵权TOPSIS&#xff01;&#xff01;matlab2023b语言运行&#xff01; 1.克里金模型&#xff08;Kriging Model&#xff09;是一种基于空间统计学的插值方法…...

驱动开发硬核特训 · Day 30(下篇): 深入解析 lm48100q I2C 音频编解码器驱动模型(基于 i.MX8MP)

作者&#xff1a;嵌入式Jerry 视频教程请关注 B 站&#xff1a;“嵌入式Jerry” 一、背景与目标 在本篇中&#xff0c;我们围绕 TI 的 lm48100q 音频编解码器 展开&#xff0c;深入讲解其作为 I2C 外设如何集成至 Linux 内核音频子系统&#xff08;ASoC&#xff09;&#xff0…...

【RAG】indexing 中的 Hierarchical Indexing(分层索引)

Hierarchical Indexing&#xff08;分层索引&#xff09; 关键词解析&#xff1a; Splits (分割): 原始文档被分割成较小的块。Cluster (聚类): 将语义上相似的文档块分组在一起。Summaries (摘要): 为每个聚类或更高层次的节点生成摘要。RAPTOR (Recursive Abstractive Proc…...

【LeetCode 42】接雨水(单调栈、DP、双指针)

题面&#xff1a; 思路&#xff1a; 能接雨水的点&#xff0c;必然是比两边都低&#xff08;小&#xff09;的点。有两种思路&#xff0c;一种是直接计算每个点的最大贡献&#xff08;也就是每个点在纵向上最多能接多少水&#xff09;&#xff0c;另一种就是计算每个点在横向上…...

【软件设计师:数据库】13.数据库控制与安全

一、数据库语言SQL SQL是结构化查询语言(Structured Query Language)的缩写,其功能包括数据查询、数据操纵、数据定义和数据控制四个部分。 SQL 语言简洁、方便实用、功能齐全,已成为目前应用最广的关系数据库语言。SQL既是自含式语言(联机交互),又是嵌入式语言(宿主语…...

PWN基础-ROP技术-ret2syscall-64位程序栈溢出利用

前置 ret2syscall 的基础我们就不做过多讲解了 利用思路与 32 位类似&#xff0c;只是传参的寄存器是&#xff1a; rdi -> rsi -> rdx -> rcx -> r8 -> r9 我们这里只用到前三个就可以了&#xff0c;以及 rax 还有一个区别就是&#xff1a; 32 位系统调用最…...

基于大模型预测的产钳助产分娩全方位研究报告

目录 一、引言 1.1 研究背景与意义 1.2 研究目的与方法 二、产钳助产分娩概述 2.1 产钳助产定义与历史 2.2 适用情况与临床意义 三、大模型预测原理与数据基础 3.1 大模型技术原理 3.2 数据收集与处理 3.3 模型训练与验证 四、术前预测与准备 4.1 大模型术前风险预…...

二叉树结构的深入学习

目录 1. 节点结构 1.1.值&#xff08;val&#xff09; 1.2.左右孩子节点 2.本质 3.类型 4.遍历方式 树是一种递归的数据结构。具有一个根节点和多个子节点&#xff0c;形成邻接关系&#xff0c;每个节点可以有零个或多个子节点。 树的定义是递归的&#xff0c;由根节点的…...

SVT-AV1源码学习-EbMotionEstimation.h 学习

#ifndef EbMotionEstimation_h //防止文件呗重复包含的宏定义开始标记 #define EbMotionEstimation_h 定义头文件标识符 #include "definitions.h" //包含定义文件 #include "coding_unit.h" //包含编码单元相关文件 #include "me_process.h" //…...

代理服务器

1.准备3台虚拟机 1台当做代理服务器&#xff1b;2台当做真实访问服务器&#xff1b;可以再来一台虚拟机当客户机&#xff0c;也可以使用主机来当客户机。 依次配置服务器 真实服务器&#xff08;配置文件无需更改&#xff09;&#xff1a; 代理服务器&#xff1a; 35 ups…...

数值分析——条件数

1. 条件数的定义与计算 条件数&#xff08;Condition Number&#xff09;用于量化矩阵或函数对输入误差的敏感程度&#xff0c;反映问题的“良态”或“病态”特性。 矩阵条件数的定义 对于一个非奇异方阵 A&#xff0c;其条件数定义为&#xff1a; κ(A)∥A∥⋅∥A−1∥ 其…...

C++ STL 入门:map 键值对容器

C STL 入门&#xff1a;map 键值对容器 一、核心特性与适用场景 map 是 C STL 提供的关联式键值容器&#xff0c;基于红黑树实现&#xff0c;具备以下核心特征&#xff1a; 特性表现形式底层原理键唯一性不允许重复键值红黑树节点键值唯一约束自动排序元素按键升序排列红黑树…...

ESP32-CAM开发板学习(一)

一、Arduino IDE搭建ESP32开发环境 1、安装 Arduino IDE 软件&#xff0c;在官网下载压缩包解压直接使用 官网链接: Arduino IDE 2、修改软件语言&#xff0c;单击左上角 File → Preferences…&#xff0c;把Language改成中文(简体)&#xff0c;保存 3、安装esp32开发板库…...

Arm核的Ubuntu系统上安装Qt

Arm核的Ubuntu系统上安装Qt 一、准备工作 确保可以连接网络 二、安装gcc 1、判断gcc是否安装 命令行输入:gcc -v 2、如果没有安装 输入命令安装: sudo apt install gcc 三、安装g++ 1、判断g++是否安装 命令行输入:g++ -v...

C++GO语言微服务和服务发现

目录 01 03-go-micro简介 02 04-服务发现的简单认识 03 05-consul的安装 04 06-consul常用的命令 05 07-注册服务到consul并验证 06 08-consul健康检查 07 09-consul结合grpc使用-上&#xff08;只实现grpc远程调用&#xff09; 08 10-consul结合grpc使用-中&#xff08…...

【随笔】Google学术:but your computer or network may be sending automated queries.

文章目录 一、问题复述二、问题原因三、解决 前提&#xff1a;你的xxx是自己做的&#xff0c;你自己可以管理&#xff0c;而不是用的那些劣质✈场。 一、问题复述 &#x1f7e2;如下图所示&#xff1a;可以打开谷歌学术&#xff0c;但是一搜索就是这个界面。 二、问题原因 …...

JavaSE核心知识点02面向对象编程02-02(封装、继承、多态)

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 JavaSE核心知识点02面向对象编程02-02&#…...

Ubuntu 服务器管理命令笔记

这份命令笔记涵盖了 Ubuntu 服务器管理的各个方面&#xff0c;包括系统更新、用户管理、安全配置、网络诊断等&#xff0c;适合日常使用与技术分享。 系统管理命令 sudo apt update && sudo apt upgrade -y # 更新系统 sudo reboot …...

航电系统之数据传输与交换篇

航电系统的数据传输与交换是航空电子领域的核心技术&#xff0c;直接关系到飞行安全、效率及任务执行能力。以下从技术架构、关键协议、应用场景、发展趋势与挑战四个维度进行系统阐述&#xff1a; 一、技术架构与核心组件 航电系统数据传输与交换采用分层化、模块化设计&…...

MATLAB 在医疗行业的应用

MATLAB 在医疗行业的应用 MATLAB 是一种强大的技术计算和模拟平台&#xff0c;在医疗行业中有着广泛的应用。日益处于数字化和智能化进程中的医疗行业&#xff0c;需要应用很多高性能的工具来支撑设备设计&#xff0c;信号分析&#xff0c;AI 项目开发等。本文将全面介绍 MATL…...

基于CNN与SHAP可解释性分析的神经网络回归预测模型【MATLAB】

基于CNN与SHAP可解释性分析的神经网络回归预测模型【MATLAB】 一、引言 在当今数据驱动的时代&#xff0c;机器学习和深度学习技术被广泛应用于各类预测任务中。其中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;因其在处理具有空间结构的数据方面表现出色&#xff0…...

第一次被AI指点出文章的问题

二十年&#xff0c;几乎从未收到过这种程度的反馈。大部分意见都是有效的批评。 1.前言 关于链家左晖的一篇评论稿 这篇文章有什么问题吗&#xff1f;所有方面都可以谈&#xff0c;包括叙述&#xff0c;用词&#xff0c;重复&#xff0c;真实性&#xff0c;偏见&#xff0c;…...

红黑树的应用场景 —— 进程调度 CFS 与内存管理

一、红黑树在操作系统中的“实战”应用 &#x1f4cc; 1. 进程调度器&#xff1a;CFS&#xff08;Completely Fair Scheduler&#xff09; CFS 是 Linux 的默认调度器&#xff08;从 2.6.23 起&#xff09;&#xff0c;它使用红黑树维护就绪队列。 ✨ 为什么用红黑树&#x…...

RHEL8搭建FOU隧道

RHEL8搭建FOU隧道 搭建FOU隧道升级内核装载模块启用 IPv4 数据包转发功能升级iproute 配置 FOU 隧道k2接收端配置k1发送端配置双向配置k1 作为接收端配置一次。k2 作为发送端配置一次。配置接口状态配置路由的下一跳IP配置路由隧道测试 参考链接&#xff1a; 搭建FOU隧道 FOU是…...

单片机自动排列上料控制程序 下

/***************上料时间参数显示******************/ void dis_timea(uchar s) { uchar x,y; uint i0; A1s/100; A2(s-A1*100)/10; A3s-A1*100-A2*10; …...

科技成果鉴定测试有哪些内容?又有什么作用?

科技成果鉴定测试是评价科技成果质量和水平的方法之一&#xff0c;通过测试&#xff0c;可以对科技成果的技术优劣进行评估&#xff0c;从而为科技创新提供参考和指导。 一、科技成果鉴定测试的内容   1.技术评审&#xff1a;通过技术专家对项目进行详细的技术分析&#xff…...