建设银行手机银行下载官方网站下载/怎么开网店

建设银行手机银行下载官方网站下载,怎么开网店,响应式网页设计ppt,北京公司建一个网站需要多少钱线程池实现学习笔记 今天花了一些时间学习和实现了线程池,收获颇丰。在这里记录一下自己的学习心得,希望对大家也有帮助。 为什么需要线程池? 在实际开发中,如果每个任务都创建一个新线程,当任务数量很大时会带来以…

线程池实现学习笔记

今天花了一些时间学习和实现了线程池,收获颇丰。在这里记录一下自己的学习心得,希望对大家也有帮助。

为什么需要线程池?

在实际开发中,如果每个任务都创建一个新线程,当任务数量很大时会带来以下问题:

  1. 线程创建和销毁的开销大

    • 创建线程需要分配内存空间
    • 需要初始化线程栈(默认大小通常为1MB)
    • 需要进行系统调用创建内核线程
    • 销毁线程需要回收资源,也会消耗系统资源
  2. 系统资源占用过多

    • 每个线程都占用一定的内存空间
    • 线程过多会导致系统内存紧张
    • 线程的上下文信息也会占用内核空间
  3. 线程数量过多导致系统不稳定

    • 超出系统支持的最大线程数限制
    • 过多的线程竞争CPU资源
    • 可能导致系统响应变慢
  4. 线程频繁切换导致CPU开销增大

    • 线程切换需要保存和恢复上下文
    • 频繁的上下文切换会降低CPU利用率
    • 影响程序的整体性能

这时候就需要线程池来解决这些问题。线程池通过复用已创建的线程来执行任务,避免了频繁创建和销毁线程的开销。

线程池的核心数据结构

首先,我们需要定义线程池的基本结构。每个结构体的设计都有其特定的用途:

typedef struct threadpool_t {pthread_t *thread;         // 线程数组,存储线程池中的线程int threadd_nums;         // 线程数量,表示池中的线程数task_queue_t que;        // 任务队列,存储待执行的任务pthread_mutex_t mutex;    // 互斥锁,用于保护共享资源pthread_cond_t cond;     // 条件变量,用于线程间的通知机制bool is_running;         // 线程池运行状态,控制线程池的生命周期
} threadpool_t;// 任务结构体:定义任务的基本单位
typedef struct task_t {void (*function)(void* arg);  // 函数指针,指向任务函数void* arg;                    // 函数参数,可以传递任意类型的数据
} task_t;// 任务队列结构体:实现任务的FIFO管理
typedef struct task_queue_t {task_t* tasks;           // 任务数组,存储队列中的任务int capacity;           // 队列容量,表示最大可以存储的任务数int size;              // 当前任务数量,表示队列中实际的任务数int front;             // 队首索引,指向第一个任务int rear;              // 队尾索引,指向下一个可以插入任务的位置
} task_queue_t;

详细实现过程

1. 任务队列的实现

任务队列采用循环队列的设计,这样可以高效地利用空间:

// 初始化队列:分配内存并初始化各项参数
void queueInit(task_queue_t* queue) {queue->capacity = QUEUE_SIZE;    // 设置队列容量queue->size = 0;                 // 初始化任务数量为0queue->front = 0;                // 队首指向0queue->rear = 0;                 // 队尾指向0// 分配任务数组内存queue->tasks = (task_t*)malloc(sizeof(task_t) * QUEUE_SIZE);
}// 添加任务:将任务添加到队列尾部
bool queuePush(task_queue_t* queue, task_t task) {// 检查队列是否已满if (queue->size >= queue->capacity) {return false;}// 将任务添加到队尾queue->tasks[queue->rear] = task;// 更新队尾位置,使用取模运算实现循环queue->rear = (queue->rear + 1) % queue->capacity;queue->size++;return true;
}// 获取任务:从队列头部取出任务
bool queuePop(task_queue_t* queue, task_t* task) {// 检查队列是否为空if (queue->size <= 0) {return false;}// 取出队首任务*task = queue->tasks[queue->front];// 更新队首位置,使用取模运算实现循环queue->front = (queue->front + 1) % queue->capacity;queue->size--;return true;
}

2. 工作线程函数实现

工作线程的实现体现了线程池的核心工作原理:

void* threadFunc(void* arg) {threadpool_t* pool = (threadpool_t*)arg;task_t task;while (pool->is_running) {  // 线程池运行状态检查pthread_mutex_lock(&pool->mutex);  // 获取互斥锁// 使用while循环是为了防止虚假唤醒while (pool->que.size == 0 && pool->is_running) {// 当队列为空时,线程等待条件变量通知pthread_cond_wait(&pool->cond, &pool->mutex);}// 再次检查运行状态,防止线程池已关闭if (!pool->is_running) {pthread_mutex_unlock(&pool->mutex);break;}// 尝试获取任务if (queuePop(&pool->que, &task)) {pthread_mutex_unlock(&pool->mutex);  // 解锁,让其他线程能够访问队列task.function(task.arg);  // 执行任务} else {pthread_mutex_unlock(&pool->mutex);}}return NULL;
}

3. 线程池的完整生命周期

初始化
void threadpoolInit(threadpool_t *pool, int num) {if (pool) {// 分配线程数组内存,使用calloc自动初始化为0pool->thread = (pthread_t *)calloc(num, sizeof(pthread_t *));pool->threadd_nums = num;  // 设置线程数量pool->is_running = true;   // 设置运行状态为true// 初始化同步原语pthread_mutex_init(&pool->mutex, NULL);  // 初始化互斥锁pthread_cond_init(&pool->cond, NULL);    // 初始化条件变量queueInit(&pool->que);                   // 初始化任务队列}
}
启动线程池
void threadpoolStart(threadpool_t *pool) {// 创建指定数量的工作线程for (int i = 0; i < pool->threadd_nums; i++) {// 创建线程,并将线程池指针作为参数传递int ret = pthread_create(&pool->thread[i], NULL, threadFunc, pool);if (ret != 0) {// 错误处理:打印错误信息并退出fprintf(stderr, "pthread_create failed: %s\n", strerror(ret));exit(1);}}
}
添加任务
void threadpoolAddTask(threadpool_t* pool, task_t task) {pthread_mutex_lock(&pool->mutex);  // 获取互斥锁// 将任务添加到队列if (queuePush(&pool->que, task)) {// 成功添加任务后,唤醒一个等待的线程pthread_cond_signal(&pool->cond);}pthread_mutex_unlock(&pool->mutex);  // 释放互斥锁
}
销毁线程池
void threadpoolDestroy(threadpool_t *pool) {if (pool) {// 设置停止标志,通知所有线程准备退出pool->is_running = false;// 唤醒所有等待的线程,使其检查运行状态并退出pthread_cond_broadcast(&pool->cond);// 等待所有线程完成当前任务并退出for (int i = 0; i < pool->threadd_nums; i++) {pthread_join(pool->thread[i], NULL);}// 按顺序释放所有资源free(pool->thread);              // 释放线程数组queueDestroy(&pool->que);        // 释放任务队列pthread_mutex_destroy(&pool->mutex);  // 销毁互斥锁pthread_cond_destroy(&pool->cond);    // 销毁条件变量}
}

实际使用示例

下面是一个完整的使用示例,展示了线程池的基本用法:

// 任务函数:打印任务编号并模拟耗时操作
void taskFunc(void* arg) {int num = *(int*)arg;printf("Task %d is running\n", num);sleep(1);  // 模拟任务执行时间free(arg); // 释放参数内存
}int main() {threadpool_t pool;// 初始化线程池,创建4个工作线程threadpoolInit(&pool, 4);threadpoolStart(&pool);// 添加10个任务到线程池for (int i = 0; i < 10; i++) {// 为每个任务分配参数内存int* arg = malloc(sizeof(int));*arg = i;// 创建任务并添加到线程池task_t task = {taskFunc, arg};threadpoolAddTask(&pool, task);}sleep(5);  // 等待任务执行完成threadpoolDestroy(&pool);  // 销毁线程池return 0;
}

遇到的问题和解决方案

在实现过程中,我遇到了一些典型的并发编程问题:

  1. 内存管理问题

    • 任务参数的内存泄漏:
      • 问题:任务参数是动态分配的,如果不及时释放会造成内存泄漏
      • 解决:在任务函数执行完成后释放参数内存
    • 线程池资源的释放顺序:
      • 问题:资源释放顺序不当可能导致访问已释放的内存
      • 解决:先停止所有线程,再按照依赖关系顺序释放资源
  2. 线程安全问题

    • 任务队列的并发访问:
      • 问题:多个线程同时操作队列可能导致数据竞争
      • 解决:使用互斥锁保护队列的所有操作
    • 条件变量的使用:
      • 问题:可能发生虚假唤醒,导致线程在队列为空时仍被唤醒
      • 解决:使用while循环检查条件,配合互斥锁使用
  3. 死锁问题

    • 在获取任务时可能发生死锁:
      • 问题:锁的获取和释放顺序不当
      • 解决:保证所有线程按相同顺序获取锁,及时释放锁
    • 销毁时的死锁:
      • 问题:线程池销毁时,线程可能还在等待条件变量
      • 解决:先设置停止标志,再唤醒所有等待的线程

性能优化

  1. 任务队列优化

    • 使用无锁队列提高并发性能:
      • CAS操作替代互斥锁
      • 使用内存屏障保证内存顺序
    • 实现动态扩容的任务队列:
      • 监控队列使用率
      • 适时调整队列容量
  2. 线程管理优化

    • 实现动态线程数量调整:
      • 根据任务量动态增减线程
      • 设置合理的线程数阈值
    • 添加线程池负载监控:
      • 记录任务执行时间
      • 统计线程利用率

后续优化方向

  1. 添加线程池状态管理

    • 运行状态监控:
      • 记录线程池运行状态
      • 提供状态查询接口
    • 任务执行统计:
      • 统计任务执行次数和时间
      • 生成性能报告
  2. 实现动态扩缩容

    • 基于任务量自动调整线程数:
      • 设置任务队列水位线
      • 根据水位线调整线程数
    • 设置最大最小线程数限制:
      • 防止线程数过多或过少
      • 保证系统稳定性
  3. 添加任务优先级支持

    • 实现优先级队列:
      • 多级任务队列
      • 优先级调度算法
    • 支持任务取消和超时:
      • 任务状态管理
      • 超时处理机制
  4. 完善错误处理机制

    • 异常处理和恢复:
      • 捕获并处理异常
      • 实现自动恢复机制
    • 日志记录系统:
      • 记录关键操作日志
      • 支持不同级别的日志

这个实现虽然还有优化空间,但已经包含了线程池的核心功能。在实际项目中,我们可以根据具体需求进行扩展和改进。

希望这篇文章能帮助到同样在学习线程池的朋友们。如果有任何问题或建议,欢迎在评论区讨论!

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

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

相关文章

CES Asia 2025赛逸展:科技浪潮中的创新与商贸盛会

在科技发展日新月异的当下&#xff0c;CES Asia 2025第七届亚洲消费电子技术贸易展&#xff08;赛逸展&#xff09;正积极筹备&#xff0c;将在北京举办&#xff0c;有望成为亚洲消费电子领域极具影响力的年度盛会。作为亚洲科技领域的重要展会&#xff0c;此次得到了数十家电子…

Windows桌面采集技术

在进入具体的方式讨论前&#xff0c;我们先看看 Windows 桌面图形界面的简化架构&#xff0c;如下图&#xff1a; 在 Windows Vista 之前&#xff0c;Windows 界面的复合画面经由 Graphics Device Interface&#xff08;以下简称 GDI&#xff09;技术直接渲染到桌面上。 在 Wi…

ElementPlus 快速入门

目录 前言 为什么要学习 ElementPlus&#xff1f; 正文 步骤 1 创建 一个工程化的vue 项目 ​2 安装 element-Plus :Form 表单 | Element Plus 1 点击 当前界面的指南 2 点击左边菜单栏上的安装&#xff0c;选择包管理器 3 运行该命令 demo(案例1 &#xff09; 步骤 …

[蓝桥杯 2023 省 A] 异或和之和

题目来自洛谷网站&#xff1a; 暴力思路&#xff1a; 先进性预处理&#xff0c;找到每个点位置的前缀异或和&#xff0c;在枚举区间。 暴力代码&#xff1a; #include<bits/stdc.h> #define int long long using namespace std; const int N 1e520;int n; int arr[N…

python学习笔记--实现简单的爬虫(二)

任务&#xff1a;爬取B站上最爱欢迎的编程课程 网址&#xff1a;编程-哔哩哔哩_bilibili 打开网页的代码模块&#xff0c;如下图&#xff1a; 标题均位于class_"bili-video-card__info--tit"的h3标签中&#xff0c;下面通过代码来实现&#xff0c;需要说明的是URL中…

windows清除电脑开机密码,可保留原本的系统和资料,不重装系统

前言 很久的一台电脑没有使用了&#xff0c;开机密码忘了&#xff0c;进不去系统 方法 1.将一个闲置u盘设置成pe盘&#xff08;注意&#xff0c;这个操作会清空原来u盘的数据&#xff0c;需要在配置前将重要数据转移走&#xff0c;数据无价&#xff0c;别因为配置这个丢了重…

5.4 位运算专题:LeetCode 137. 只出现一次的数字 II

1. 题目链接 LeetCode 137. 只出现一次的数字 II 2. 题目描述 给定一个整数数组 nums&#xff0c;其中每个元素均出现 三次&#xff0c;除了一个元素只出现 一次。请找出这个只出现一次的元素。 要求&#xff1a; 时间复杂度为 O(n)&#xff0c;空间复杂度为 O(1)。 示例&a…

C语言:扫雷

在编程的世界里&#xff0c;扫雷游戏是一个经典的实践项目。它不仅能帮助我们巩固编程知识&#xff0c;还能锻炼逻辑思维和解决问题的能力。今天&#xff0c;就让我们一起用 C 语言来实现这个有趣的游戏&#xff0c;并且通过图文并茂的方式&#xff0c;让每一步都清晰易懂 1. 游…

【论文#目标检测】YOLO9000: Better, Faster, Stronger

目录 摘要1.引言2.更好&#xff08;Better&#xff09;3.更快&#xff08;Faster&#xff09;4.更健壮&#xff08;Stronger&#xff09;使用 WordTree 组合数据集联合分类和检测评估 YOLO9000 5.结论 Author: Joseph Redmon; Ali Farhadi Published in: 2017 IEEE Conference …

大数据运维实战之YARN任务内存泄露排查实战:从节点掉线到精准定位的完整指南

1.问题背景&#xff1a;集群内存风暴引发的危机 最近某大数据集群频繁出现节点掉线事故&#xff0c;物理内存监控持续爆红。运维人员发现当节点内存使用率达到95%以上时&#xff0c;机器会进入不可响应状态&#xff0c;最终导致服务中断。这种"内存雪崩"现象往往由单…

AI+金融 应用 使用DeepSeek、Qwen等大模型输入自然语言,得到通达信等行情软件公式代码,导入后使用

AI金融 应用 使用DeepSeek、Qwen等大模型输入自然语言&#xff0c;得到通达信等行情软件公式代码&#xff0c;导入后使用。不会编程&#xff0c;也能行情软件中实现个性化条件选股&#xff0c;个性化技术指标。 AIbxm低估值趋势选股策略&#xff0c;参考提示词&#xff1a; 编…

多语言语料库万卷·丝路2.0开源,数据模态全面升级,搭建文化交流互鉴AI桥梁

3月22日&#xff0c;上海人工智能实验室&#xff08;上海AI实验室&#xff09;联合新华社新闻信息中心、上海外国语大学、外研在线等&#xff0c;发布全新升级的“万卷丝路2.0”多语言语料库&#xff0c;通过构建多语言开源数据底座&#xff0c;以人工智能赋能“一带一路”高质…

多语言生成语言模型的少样本学习

摘要 大规模生成语言模型&#xff0c;如GPT-3&#xff0c;是极具竞争力的少样本学习模型。尽管这些模型能够共同表示多种语言&#xff0c;但其训练数据以英语为主&#xff0c;这可能限制了它们的跨语言泛化能力。在本研究中&#xff0c;我们在一个涵盖多种语言的语料库上训练了…

Linux运维篇-系统io调优

目录 磁盘文件系统虚拟文件系统 文件系统的工作原理文件系统 I/OI/O 的分类缓冲与非缓冲 I/O直接与非直接 I/O阻塞与非阻塞 I/O同步与异步 I/O 查看文件系统容量目录项和索引节点缓存 通用块层I/O 栈磁盘性能指标磁盘 I/O 观测进程 I/O 观测I/O瓶颈的排查思路思路一思路二 I/O优…

C语言笔记(鹏哥)上课板书+课件汇总(动态内存管理)--数据结构常用

动态内存管理 引言&#xff1a;将内存升起一段空间存放数据有几种手段 创建变量&#xff1a;存放一个值创建数组&#xff1a;存放多个连续的一组值 以上开辟的内存空间是固定的&#xff0c;创建大了&#xff0c;空间浪费&#xff0c;创建小了&#xff0c;空间不够。并且一旦…

本地安装deepseek大模型,并使用 python 调用

首先进入 ollama 官网 https://ollama.com/点击下载 下载完成后所有都是下一步&#xff0c;就可以 点击搜索 Models &#xff1a; https://ollama.com/search然后点击下载&#xff1a; 选择后复制: ollama run deepseek-r1:32b例如&#xff1a; 让它安装完成后&#xff1…

Linux wifi driver 注册和设备探测流程

基础流程 wifi驱动加载&#xff08;insmod或者modprobe&#xff09; 设备驱动匹配探测&#xff08;我们常见的probe函数&#xff09; 整体流程 驱动加载 → 注册支持设备 → 设备插入 → 匹配驱动 → 初始化硬件 → 创建网络接口 明确两点 两个流程 驱动加载&#xf…

【机器人】复现 GrainGrasp 精细指导的灵巧手抓取

GrainGrasp为每个手指提供细粒度的接触指导&#xff0c;为灵巧手生成精细的抓取策略。 通过单独调整每个手指的接触来实现更稳定的抓取&#xff0c;从而提供了更接近人类能力的抓取指导。 论文地址&#xff1a;GrainGrasp: Dexterous Grasp Generation with Fine-grained Con…

快速部署Samba共享服务器作为k8s后端存储

由于Ceph Squid&#xff08;v19.2.1&#xff09;‌不原生支持直接导出 SMB 服务器‌&#xff0c;需通过手动集成 Samba 或其他第三方工具实现‌ 所以直接部署最简单的 安装软件包 apt install samba编辑配置文件 vim /etc/samba/smb.conf在最末尾添加以下 # cp /etc/samba/sm…

【MYSQL】索引和事务

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 本期内容讲解 MySQL 中的索引和事务&#xff0c;在学习的过程中&#xff0c;我们需要经常问自己为什么 文章目录 1. 索…