Linux下线程池的实现

AutoSAR系列讲解(入门篇)4.1-BSW概述 BSW概述,主要讲解BSW的结构组成 阅读详情


  什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽视,这时也是线程池该出场的机会了。如果线程创建和销毁时间相比任务执行时间可以忽略不计,则没有必要使用线程池了。


    下面是Linux系统下用C语言创建的一个线程池。线程池会维护一个任务链表(每个CThread_worker结构就是一个任务)。
    pool_init()函数预先创建好max_thread_num个线程,每个线程执thread_routine ()函数。该函数中
  1. while (pool->cur_queue_size == 0)
  2. {
  3.       pthread_cond_wait (&(pool->queue_ready),&(pool->queue_lock));
  4. }
表示如果任务链表中没有任务,则该线程出于阻塞等待状态。否则从队列中取出任务并执行。
    
    pool_add_worker()函数向线程池的任务链表中加入一个任务,加入后通过调用pthread_cond_signal (&(pool->queue_ready))唤醒一个出于阻塞状态的线程(如果有的话)。
    
    pool_destroy ()函数用于销毁线程池,线程池任务链表中的任务不会再被执行,但是正在运行的线程会一直把任务运行完后再退出。
    
    下面贴出完整代码
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <pthread.h>
  6. #include <assert.h>
  7. /*
  8. *线程池里所有运行和等待的任务都是一个CThread_worker
  9. *由于所有任务都在链表里,所以是一个链表结构
  10. */
  11. typedef struct worker
  12. {
  13.     /*回调函数,任务运行时会调用此函数,注意也可声明成其它形式*/
  14.     void *(*process) (void *arg);
  15.     void *arg;/*回调函数的参数*/
  16.     struct worker *next;
  17. } CThread_worker;

  18. /*线程池结构*/
  19. typedef struct
  20. {
  21.     pthread_mutex_t queue_lock;
  22.     pthread_cond_t queue_ready;
  23.     /*链表结构,线程池中所有等待任务*/
  24.     CThread_worker *queue_head;
  25.     /*是否销毁线程池*/
  26.     int shutdown;
  27.     pthread_t *threadid;
  28.     /*线程池中允许的活动线程数目*/
  29.     int max_thread_num;
  30.     /*当前等待队列的任务数目*/
  31.     int cur_queue_size;
  32. } CThread_pool;

  33. int pool_add_worker (void *(*process) (void *arg), void *arg);
  34. void *thread_routine (void *arg);

  35. static CThread_pool *pool = NULL;
  36. void
  37. pool_init (int max_thread_num)
  38. {
  39.     pool = (CThread_pool *) malloc (sizeof (CThread_pool));
  40.     pthread_mutex_init (&(pool->queue_lock), NULL);
  41.     pthread_cond_init (&(pool->queue_ready), NULL);
  42.     pool->queue_head = NULL;
  43.     pool->max_thread_num = max_thread_num;
  44.     pool->cur_queue_size = 0;
  45.     pool->shutdown = 0;
  46.     pool->threadid =
  47.         (pthread_t *) malloc (max_thread_num * sizeof (pthread_t));
  48.     int i = 0;
  49.     for (i = 0; i < max_thread_num; i++)
  50.     { 
  51.         pthread_create (&(pool->threadid[i]), NULL, thread_routine,
  52.                 NULL);
  53.     }
  54. }

  55. /*向线程池中加入任务*/
  56. int
  57. pool_add_worker (void *(*process) (void *arg), void *arg)
  58. {
  59.     /*构造一个新任务*/
  60.     CThread_worker *newworker =
  61.         (CThread_worker *) malloc (sizeof (CThread_worker));
  62.     newworker->process = process;
  63.     newworker->arg = arg;
  64.     newworker->next = NULL;/*别忘置空*/
  65.     pthread_mutex_lock (&(pool->queue_lock));
  66.     /*将任务加入到等待队列中*/
  67.     CThread_worker *member = pool->queue_head;
  68.     if (member != NULL)
  69.     {
  70.         while (member->next != NULL)
  71.             member = member->next;
  72.         member->next = newworker;
  73.     }
  74.     else
  75.     {
  76.         pool->queue_head = newworker;
  77.     }
  78.     assert (pool->queue_head != NULL);
  79.     pool->cur_queue_size++;
  80.     pthread_mutex_unlock (&(pool->queue_lock));
  81.     /*好了,等待队列中有任务了,唤醒一个等待线程;
  82.     注意如果所有线程都在忙碌,这句没有任何作用*/
  83.     pthread_cond_signal (&(pool->queue_ready));
  84.     return 0;
  85. }

  86. /*销毁线程池,等待队列中的任务不会再被执行,但是正在运行的线程会一直
  87. 把任务运行完后再退出*/
  88. int
  89. pool_destroy ()
  90. {
  91.     if (pool->shutdown)
  92.         return -1;/*防止两次调用*/
  93.     pool->shutdown = 1;
  94.     /*唤醒所有等待线程,线程池要销毁了*/
  95.     pthread_cond_broadcast (&(pool->queue_ready));
  96.     /*阻塞等待线程退出,否则就成僵尸了*/
  97.     int i;
  98.     for (i = 0; i < pool->max_thread_num; i++)
  99.         pthread_join (pool->threadid[i], NULL);
  100.     free (pool->threadid);
  101.     /*销毁等待队列*/
  102.     CThread_worker *head = NULL;
  103.     while (pool->queue_head != NULL)
  104.     {
  105.         head = pool->queue_head;
  106.         pool->queue_head = pool->queue_head->next;
  107.         free (head);
  108.     }
  109.     /*条件变量和互斥量也别忘了销毁*/
  110.     pthread_mutex_destroy(&(pool->queue_lock));
  111.     pthread_cond_destroy(&(pool->queue_ready));
  112.     
  113.     free (pool);
  114.     /*销毁后指针置空是个好习惯*/
  115.     pool=NULL;
  116.     return 0;
  117. }

  118. void *
  119. thread_routine (void *arg)
  120. {
  121.     printf ("starting thread 0x%x/n", pthread_self ());
  122.     while (1)
  123.     {
  124.         pthread_mutex_lock (&(pool->queue_lock));
  125.         /*如果等待队列为0并且不销毁线程池,则处于阻塞状态; 注意
  126.         pthread_cond_wait是一个原子操作,等待前会解锁,唤醒后会加锁*/
  127.         while (pool->cur_queue_size == 0 && !pool->shutdown)
  128.         {
  129.             printf ("thread 0x%x is waiting/n", pthread_self ());
  130.             pthread_cond_wait (&(pool->queue_ready), &(pool->queue_lock));
  131.         }
  132.         /*线程池要销毁了*/
  133.         if (pool->shutdown)
  134.         {
  135.             /*遇到break,continue,return等跳转语句,千万不要忘记先解锁*/
  136.             pthread_mutex_unlock (&(pool->queue_lock));
  137.             printf ("thread 0x%x will exit/n", pthread_self ());
  138.             pthread_exit (NULL);
  139.         }
  140.         printf ("thread 0x%x is starting to work/n", pthread_self ());
  141.         /*assert是调试的好帮手*/
  142.         assert (pool->cur_queue_size != 0);
  143.         assert (pool->queue_head != NULL);
  144.         
  145.         /*等待队列长度减去1,并取出链表中的头元素*/
  146.         pool->cur_queue_size--;
  147.         CThread_worker *worker = pool->queue_head;
  148.         pool->queue_head = worker->next;
  149.         pthread_mutex_unlock (&(pool->queue_lock));
  150.         /*调用回调函数,执行任务*/
  151.         (*(worker->process)) (worker->arg);
  152.         free (worker);
  153.         worker = NULL;
  154.     }
  155.     /*这一句应该是不可达的*/
  156.     pthread_exit (NULL);
  157. }
    下面是测试代码
  1. void *
  2. myprocess (void *arg)
  3. {
  4.     printf ("threadid is 0x%x, working on task %d/n", pthread_self (),*(int *) arg);
  5.     sleep (1);/*休息一秒,延长任务的执行时间*/
  6.     return NULL;
  7. }
  8. int
  9. main (int argc, char **argv)
  10. {
  11.     pool_init (3);/*线程池中最多三个活动线程*/
  12.     
  13.     /*连续向池中投入10个任务*/
  14.     int *workingnum = (int *) malloc (sizeof (int) * 10);
  15.     int i;
  16.     for (i = 0; i < 10; i++)
  17.     {
  18.         workingnum[i] = i;
  19.         pool_add_worker (myprocess, &workingnum[i]);
  20.     }
  21.     /*等待所有任务完成*/
  22.     sleep (5);
  23.     /*销毁线程池*/
  24.     pool_destroy ();
  25.     free (workingnum);
  26.     return 0;
  27. }
将上述所有代码放入threadpool.c文件中,
在Linux输入编译命令
$ gcc -o threadpool threadpool.c -lpthread

以下是运行结果
starting thread 0xb7df6b90
thread 0xb7df6b90 is waiting
starting thread 0xb75f5b90
thread 0xb75f5b90 is waiting
starting thread 0xb6df4b90
thread 0xb6df4b90 is waiting
thread 0xb7df6b90 is starting to work
threadid is 0xb7df6b90, working on task 0
thread 0xb75f5b90 is starting to work
threadid is 0xb75f5b90, working on task 1
thread 0xb6df4b90 is starting to work
threadid is 0xb6df4b90, working on task 2
thread 0xb7df6b90 is starting to work
threadid is 0xb7df6b90, working on task 3
thread 0xb75f5b90 is starting to work
threadid is 0xb75f5b90, working on task 4
thread 0xb6df4b90 is starting to work
threadid is 0xb6df4b90, working on task 5
thread 0xb7df6b90 is starting to work
threadid is 0xb7df6b90, working on task 6
thread 0xb75f5b90 is starting to work
threadid is 0xb75f5b90, working on task 7
thread 0xb6df4b90 is starting to work
threadid is 0xb6df4b90, working on task 8
thread 0xb7df6b90 is starting to work
threadid is 0xb7df6b90, working on task 9
thread 0xb75f5b90 is waiting
thread 0xb6df4b90 is waiting
thread 0xb7df6b90 is waiting
thread 0xb75f5b90 will exit
thread 0xb6df4b90 will exit

thread 0xb7df6b90 will exit



转自:http://blog.youkuaiyun.com/zouxinfox/article/details/3560891

Codex 100个真实案例 - 用AI绘制CAD机械图纸(工程师看了直呼内行) 本案例将展示如何用 Codex 生成 Python 脚本,通过 `ezdxf` 库绘制标准 DXF 格式的 CAD 机械图纸。我们会从零开始,逐步实现直线、圆、圆弧、标注等基本图形元素,最终绘制出一张包含主视图、俯视图、尺寸标注、标题栏和技术要求的完整法兰盘零件图。还会演示参数化批量生成不同规格零件图和自动 BOM 物料清单,生成的 DXF 文件可直接在 AutoCAD、FreeCAD 中打开。全程用自然语言驱动 Codex,工程师看完直接上手! 阅读详情

相关推荐

音频DSP开发中的‘隐藏关卡’:那些SigmaStudio未公开的模块计算秘籍

本文深入探讨音频DSP开发中SigmaStudio未公开的模块计算秘籍,重点解析动态范围控制、均衡器参数映射和混响算法优化等核心模块计算公式。通过实际案例揭示如何利用这些非官方技巧提升音频质量与系统性能,为ADI DSP开发者提供宝贵的实战经验。

water的专栏 911

一个Linux下C线程池的实现

    什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽视,这时也是线程池该出场的机会了。如果线程创建和销毁时间相比任务执行时间可以忽略不计,则没有必要使用线程池了。    下面是Linux系统下用C语言创建的一个线程池。线程池会维护一个任务链表(每个CThread_worker结构就是一个任务)。    p

邹鑫的专栏 2万+

[pytorch] MedicalNet 3D Resnet预训练模型迁移学习实战:从分割到分类的代码改造

本文详细介绍了如何利用PyTorch对MedicalNet 3D ResNet预训练模型进行迁移学习,从分割任务改造为分类任务。通过解析模型结构、调整分类头、加载预训练权重及优化训练策略,帮助开发者在医疗影像领域快速实现高效模型部署。文章还涵盖了数据预处理、增强技巧及模型轻量化等实用内容。

kmeans3miner的博客 246

[Linux程序设计] C语言实现线程池

在linux环境下使用C语言完成线程池的创建。在程序中多次创建线程会占用CPU时间,如何保证一个线程可以复用,提高CPU的利用率,线程池可以解决这些问题。

weixin_62337145的博客 1293

奇迹mu服务端DATA文件解析:从基础配置到高级玩法

本文深入解析奇迹MU服务端DATA文件的核心配置与高级玩法,涵盖基础设置、怪物AI系统、技能战斗机制、副本事件管理及物品商城定制。通过详细示例和实用技巧,帮助开发者掌握从经验倍率调整到动态事件触发的全方位配置方法,实现个性化的私服搭建与运营。

weixin_29254673的博客 532

C++碰撞检测库FCL安装(MinGW,CMake)

FCL碰撞检测库、libccd\Eigen库编译配置,全流程问题记录

weixin_45650767的博客 4676

【Linux | 详解线程池原理及C语言的实现】

【Linux | 详解线程池原理及C语言的实现】

Sugar_wolf的博客 573

RK3308B开发板WiFi+蓝牙一体模组RTL8821CS驱动移植保姆级教程(含DTS配置与避坑点)

本文提供RK3308B开发板RTL8821CS WiFi+蓝牙模组驱动移植的完整教程,涵盖SDK环境配置、DTS设备树设置、内核编译优化及功能验证全流程。重点解析引脚复用冲突、电源管理等关键配置,并给出常见错误解决方案,帮助开发者快速实现双模通信功能。

weixin_42531163的博客 398

一文搞懂系列——Linux C线程池技术

实际上,我觉得在诊断项目中,线程池技术是非必要的。因此它不会涉及到大量的请求,以及每一个请求处理,一般都会比较耗时。参考:https://www.cnblogs.com/zhaoosheLBJ/p/9337291.html。

点滴路程 1396

【虚幻引擎UE】UE5 阴影异常与优化

【虚幻引擎UE】UE5 阴影异常与优化解决方案合集

灵境引路人 3万+

二叉树三种遍历(动态图+代码深入理解)

文章目录一、图示理解(图片是一位前辈所留,在此感谢)1、先序遍历2、中序遍历3、后序遍历4、层序遍历二、深入理解三种遍历让我们来理解一下绕着外围跑一整圈的真正含义是:遍历所有结点时,都先往左孩子走,再往右孩子走。下面做一个实例吧三、代码实现加以理解以下是C语言全部代码实现下面是同样的例子用c++实现,大家可以参考一下 一、图示理解(图片是一位前辈所留,在此感谢) 1、先序遍历 先序遍历可以想象成,...

流楚丶格念的博客 3万+

Linux下c语言的线程池(分模块讲解)

关于C语言线程池的理解(包含全部的模块以及一个小测试)

记录一位C++爱好者的笔记 1336

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

linux下线程池实现

linux下线程池实现 转自:http://blog.youkuaiyun.com/lmh12506/article/details/7753952 前段时间在github上开了个库,准备实现自己的线程池的,因为换工作的事,一直也没有实现,参考这篇文章准备着手实现一下。 什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执...

qq_43026520的博客 308

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Linux下线程池实现

一、预备知识 1、线程: 线程同进程类似,是允许应用程序并发执行多个任务的一种机制,一个进程可以包含多个线程。在Linux下,进程是系统资源的最小分配单位,线程则是最小的执行单位,一个进程中至少有一个线程作为程序执行的主线程。因为进程作为系统资源的最小分配单位,而线程在进程的基础...

127

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Linux下线程池(POSIX线程)的详细实现,包含完整代码和详细注释

Linux/C++线程池(POSIX线程),包含详细代码与注释

m0_51932378的博客 1542

Linux平台下线程池的原理及实现

什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽视,这时也是线程池该出场的机会了。如果线程创建和销毁时间相比任务执行时间可以忽略不计,则没有必要使用线程池了。    下面是Linux系统下用C语言创建的一个线程池。线程池会维护一个任务链表(每个CThread_worker结构就是一个任务)。

5055

Linux下线程池源码实现

线程池: 初始化阶段创建有最大数量限制的线程,以及一个线程安全的任务队列,若有任务需要处理,则将任务抛入线程池中,线程池中的的线程就会去处理这个任务。 优点 1.避免峰值压力下,资源耗尽的风险; 2.节省线程创建、销毁带来的时间成本 为什么需要线程池? 针对请求处理,单个线程处理,效率过低,采用多线程处理。 但是每个请求都创建一个线程,有可能线程创建过多,效率没有增加反而降低/瞬间资源消耗过度,程...

qq_43735092的博客 206

C++ Linux下线程池的实现

线程池提供设计图 转载于:https://www.cnblogs.com/zhanggaofeng/p/9338601.html

weixin_30505043的博客 72

简单实现Linux下线程池

最近在Linux下使用mysql时有时会报查询异常,看网上解决方案是多次并发使用,通过gdb调试也找到问题,主要是上次查询结果集未释放,最终导致如此。 大佬说根本解决方案还是线程池,就去看了线程池的一些内容,记录此篇主要是用于自己cv,怕自己忘记 1、threadPool.cpp #include "threadPool.h" void* threadRoutine(void* arg); threadPool* createPool(int max_thread_num, int max_task_qu

Ymqcd的博客 367

linux下线程池原理及实现

什么是线程池? 诸如web服务器、数据库服务器、文件服务器和邮件服务器等许多服务器应用都面向处理来自某些远程来源的大量短小的任务。构建服务器应用程序的一个过于简单的模型是:每当一个请求到达就创建一个新的服务对象,然后在新的服务对象中为请求服务。但当有大量请求并发访问时,服务器不断的创建和销毁对象的开销很大。所以提高服务器效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对

scmuzi18的博客 1536

linux下线程池的实现(c++)

linux下线程池的实现(c++)   2012-12-07 16:11:44|  分类: 电子安防项目|举报|字号 订阅 参考:http://hi.baidu.com/boahegcrmdghots/item/f3ca1a3c2d47fcc52e8ec2e1 /* * autoptr.h * *  Created on: 2012-12-7 *    

zdy0_2004的专栏 606
上一篇: 可重入函数和线程安全的对比
下一篇: Linux高性能服务器之多路转接(1)----select模型实现
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值