简单Linux C线程池

实现Linux下的C语言简单线程池编程 线程池的基本原理是在程序启动时创建一定数量的线程,并将它们保存在一个线程池中。当需要执行某个任务时,可以从线程池中获取一个空闲的线程,并将任务分配给该线程执行。通过使用线程池,我们可以更加高效地管理和复用线程,提高程序的性能和效率。线程池是一种常用的并发编程技术,它可以在多线程环境下管理和复用线程,提高程序的性能和效率。在本篇文章中,我们将使用C语言实现一个简单的线程池,并介绍其基本原理和代码实现。函数用于向线程池添加任务,它会将任务添加到任务队列中,并通知一个等待中的线程去执行任务。 阅读详情

转载地址:http://www.cnblogs.com/venow/archive/2012/11/22/2779667.html、

大多数的网络服务器,包括Web服务器都具有一个特点,就是单位时间内必须处理数目巨大的连接请求,但是处理时间却是比较短的。在传统的多线程服务器模型中是这样实现的:一旦有个请求到达,就创建一个新的线程,由该线程执行任务,任务执行完毕之后,线程就退出。这就是"即时创建,即时销毁"的策略。尽管与创建进程相比,创建线程的时间已经大大的缩短,但是如果提交给线程的任务是执行时间较短,而且执行次数非常频繁,那么服务器就将处于一个不停的创建线程和销毁线程的状态。这笔开销是不可忽略的,尤其是线程执行的时间非常非常短的情况。

  线程池就是为了解决上述问题的,它的实现原理是这样的:在应用程序启动之后,就马上创建一定数量的线程,放入空闲的队列中。这些线程都是处于阻塞状态,这些线程只占一点内存,不占用CPU。当任务到来后,线程池将选择一个空闲的线程,将任务传入此线程中运行。当所有的线程都处在处理任务的时候,线程池将自动创建一定的数量的新线程,用于处理更多的任务。执行任务完成之后线程并不退出,而是继续在线程池中等待下一次任务。当大部分线程处于阻塞状态时,线程池将自动销毁一部分的线程,回收系统资源。

  下面是一个简单线程池的实现,这个线程池的代码是我参考网上的一个例子实现的,由于找不到出处了,就没办法注明参考自哪里了。它的方案是这样的:程序启动之前,初始化线程池,启动线程池中的线程,由于还没有任务到来,线程池中的所有线程都处在阻塞状态,当一有任务到达就从线程池中取出一个空闲线程处理,如果所有的线程都处于工作状态,就添加到队列,进行排队。如果队列中的任务个数大于队列的所能容纳的最大数量,那就不能添加任务到队列中,只能等待队列不满才能添加任务到队列中。

  主要由两个文件组成一个threadpool.h头文件和一个threadpool.c源文件组成。源码中已有重要的注释,就不加以分析了。

  threadpool.h文件:

复制代码
struct job
{
    void* (*callback_function)(void *arg);    //线程回调函数
    void *arg;                                //回调函数参数
    struct job *next;
};

struct threadpool
{
    int thread_num;                   //线程池中开启线程的个数
    int queue_max_num;                //队列中最大job的个数
    struct job *head;                 //指向job的头指针
    struct job *tail;                 //指向job的尾指针
    pthread_t *pthreads;              //线程池中所有线程的pthread_t
    pthread_mutex_t mutex;            //互斥信号量
    pthread_cond_t queue_empty;       //队列为空的条件变量
    pthread_cond_t queue_not_empty;   //队列不为空的条件变量
    pthread_cond_t queue_not_full;    //队列不为满的条件变量
    int queue_cur_num;                //队列当前的job个数
    int queue_close;                  //队列是否已经关闭
    int pool_close;                   //线程池是否已经关闭
};

//================================================================================================
//函数名:                   threadpool_init
//函数描述:                 初始化线程池
//输入:                    [in] thread_num     线程池开启的线程个数
//                         [in] queue_max_num  队列的最大job个数 
//输出:                    无
//返回:                    成功:线程池地址 失败:NULL
//================================================================================================
struct threadpool* threadpool_init(int thread_num, int queue_max_num);

//================================================================================================
//函数名:                    threadpool_add_job
//函数描述:                  向线程池中添加任务
//输入:                     [in] pool                  线程池地址
//                          [in] callback_function     回调函数
//                          [in] arg                     回调函数参数
//输出:                     无
//返回:                     成功:0 失败:-1
//================================================================================================
int threadpool_add_job(struct threadpool *pool, void* (*callback_function)(void *arg), void *arg);

//================================================================================================
//函数名:                    threadpool_destroy
//函数描述:                   销毁线程池
//输入:                      [in] pool                  线程池地址
//输出:                      无
//返回:                      成功:0 失败:-1
//================================================================================================
int threadpool_destroy(struct threadpool *pool);

//================================================================================================
//函数名:                    threadpool_function
//函数描述:                  线程池中线程函数
//输入:                     [in] arg                  线程池地址
//输出:                     无  
//返回:                     无
//================================================================================================
void* threadpool_function(void* arg);
复制代码

  threadpool.c文件:

复制代码
#include "threadpool.h"

struct threadpool* threadpool_init(int thread_num, int queue_max_num)
{
    struct threadpool *pool = NULL;
    do 
    {
        pool = malloc(sizeof(struct threadpool));
        if (NULL == pool)
        {
            printf("failed to malloc threadpool!\n");
            break;
        }
        pool->thread_num = thread_num;
        pool->queue_max_num = queue_max_num;
        pool->queue_cur_num = 0;
        pool->head = NULL;
        pool->tail = NULL;
        if (pthread_mutex_init(&(pool->mutex), NULL))
        {
            printf("failed to init mutex!\n");
            break;
        }
        if (pthread_cond_init(&(pool->queue_empty), NULL))
        {
            printf("failed to init queue_empty!\n");
            break;
        }
        if (pthread_cond_init(&(pool->queue_not_empty), NULL))
        {
            printf("failed to init queue_not_empty!\n");
            break;
        }
        if (pthread_cond_init(&(pool->queue_not_full), NULL))
        {
            printf("failed to init queue_not_full!\n");
            break;
        }
        pool->pthreads = malloc(sizeof(pthread_t) * thread_num);
        if (NULL == pool->pthreads)
        {
            printf("failed to malloc pthreads!\n");
            break;
        }
        pool->queue_close = 0;
        pool->pool_close = 0;
        int i;
        for (i = 0; i < pool->thread_num; ++i)
        {
            pthread_create(&(pool->pthreads[i]), NULL, threadpool_function, (void *)pool);
        }
        
        return pool;    
    } while (0);
    
    return NULL;
}

int threadpool_add_job(struct threadpool* pool, void* (*callback_function)(void *arg), void *arg)
{
    assert(pool != NULL);
    assert(callback_function != NULL);
    assert(arg != NULL);

    pthread_mutex_lock(&(pool->mutex));
    while ((pool->queue_cur_num == pool->queue_max_num) && !(pool->queue_close || pool->pool_close))
    {
        pthread_cond_wait(&(pool->queue_not_full), &(pool->mutex));   //队列满的时候就等待
    }
    if (pool->queue_close || pool->pool_close)    //队列关闭或者线程池关闭就退出
    {
        pthread_mutex_unlock(&(pool->mutex));
        return -1;
    }
    struct job *pjob =(struct job*) malloc(sizeof(struct job));
    if (NULL == pjob)
    {
        pthread_mutex_unlock(&(pool->mutex));
        return -1;
    } 
    pjob->callback_function = callback_function;    
    pjob->arg = arg;
    pjob->next = NULL;
    if (pool->head == NULL)   
    {
        pool->head = pool->tail = pjob;
        pthread_cond_broadcast(&(pool->queue_not_empty));  //队列空的时候,有任务来时就通知线程池中的线程:队列非空
    }
    else
    {
        pool->tail->next = pjob;
        pool->tail = pjob;    
    }
    pool->queue_cur_num++;
    pthread_mutex_unlock(&(pool->mutex));
    return 0;
}

void* threadpool_function(void* arg)
{
    struct threadpool *pool = (struct threadpool*)arg;
    struct job *pjob = NULL;
    while (1)  //死循环
    {
        pthread_mutex_lock(&(pool->mutex));
        while ((pool->queue_cur_num == 0) && !pool->pool_close)   //队列为空时,就等待队列非空
        {
            pthread_cond_wait(&(pool->queue_not_empty), &(pool->mutex));
        }
        if (pool->pool_close)   //线程池关闭,线程就退出
        {
            pthread_mutex_unlock(&(pool->mutex));
            pthread_exit(NULL);
        }
        pool->queue_cur_num--;
        pjob = pool->head;
        if (pool->queue_cur_num == 0)
        {
            pool->head = pool->tail = NULL;
        }
        else 
        {
            pool->head = pjob->next;
        }
        if (pool->queue_cur_num == 0)
        {
            pthread_cond_signal(&(pool->queue_empty));        //队列为空,就可以通知threadpool_destroy函数,销毁线程函数
        }
        if (pool->queue_cur_num == pool->queue_max_num - 1)
        {
            pthread_cond_broadcast(&(pool->queue_not_full));  //队列非满,就可以通知threadpool_add_job函数,添加新任务
        }
        pthread_mutex_unlock(&(pool->mutex));
        
        (*(pjob->callback_function))(pjob->arg);   //线程真正要做的工作,回调函数的调用
        free(pjob);
        pjob = NULL;    
    }
}
int threadpool_destroy(struct threadpool *pool)
{
    assert(pool != NULL);
    pthread_mutex_lock(&(pool->mutex));
    if (pool->queue_close || pool->pool_close)   //线程池已经退出了,就直接返回
    {
        pthread_mutex_unlock(&(pool->mutex));
        return -1;
    }
    
    pool->queue_close = 1;        //置队列关闭标志
    while (pool->queue_cur_num != 0)
    {
        pthread_cond_wait(&(pool->queue_empty), &(pool->mutex));  //等待队列为空
    }    
    
    pool->pool_close = 1;      //置线程池关闭标志
    pthread_mutex_unlock(&(pool->mutex));
    pthread_cond_broadcast(&(pool->queue_not_empty));  //唤醒线程池中正在阻塞的线程
    pthread_cond_broadcast(&(pool->queue_not_full));   //唤醒添加任务的threadpool_add_job函数
    int i;
    for (i = 0; i < pool->thread_num; ++i)
    {
        pthread_join(pool->pthreads[i], NULL);    //等待线程池的所有线程执行完毕
    }
    
    pthread_mutex_destroy(&(pool->mutex));          //清理资源
    pthread_cond_destroy(&(pool->queue_empty));
    pthread_cond_destroy(&(pool->queue_not_empty));   
    pthread_cond_destroy(&(pool->queue_not_full));    
    free(pool->pthreads);
    struct job *p;
    while (pool->head != NULL)
    {
        p = pool->head;
        pool->head = p->next;
        free(p);
    }
    free(pool);
    return 0;
}
复制代码

  测试文件main.c文件:

复制代码
#include "threadpool.h"

void* work(void* arg)
{
    char *p = (char*) arg;
    printf("threadpool callback fuction : %s.\n", p);
    sleep(1);
}

int main(void)
{
    struct threadpool *pool = threadpool_init(10, 20);
    threadpool_add_job(pool, work, "1");
    threadpool_add_job(pool, work, "2");
    threadpool_add_job(pool, work, "3");
    threadpool_add_job(pool, work, "4");
    threadpool_add_job(pool, work, "5");
    threadpool_add_job(pool, work, "6");
    threadpool_add_job(pool, work, "7");
    threadpool_add_job(pool, work, "8");
    threadpool_add_job(pool, work, "9");
    threadpool_add_job(pool, work, "10");
    threadpool_add_job(pool, work, "11");
    threadpool_add_job(pool, work, "12");
    threadpool_add_job(pool, work, "13");
    threadpool_add_job(pool, work, "14");
    threadpool_add_job(pool, work, "15");
    threadpool_add_job(pool, work, "16");
    threadpool_add_job(pool, work, "17");
    threadpool_add_job(pool, work, "18");
    threadpool_add_job(pool, work, "19");
    threadpool_add_job(pool, work, "20");
    threadpool_add_job(pool, work, "21");
    threadpool_add_job(pool, work, "22");
    threadpool_add_job(pool, work, "23");
    threadpool_add_job(pool, work, "24");
    threadpool_add_job(pool, work, "25");
    threadpool_add_job(pool, work, "26");
    threadpool_add_job(pool, work, "27");
    threadpool_add_job(pool, work, "28");
    threadpool_add_job(pool, work, "29");
    threadpool_add_job(pool, work, "30");
    threadpool_add_job(pool, work, "31");
    threadpool_add_job(pool, work, "32");
    threadpool_add_job(pool, work, "33");
    threadpool_add_job(pool, work, "34");
    threadpool_add_job(pool, work, "35");
    threadpool_add_job(pool, work, "36");
    threadpool_add_job(pool, work, "37");
    threadpool_add_job(pool, work, "38");
    threadpool_add_job(pool, work, "39");
    threadpool_add_job(pool, work, "40");

    sleep(5);
    threadpool_destroy(pool);
    return 0;
}
复制代码

  用gcc编译,运行就可以看到效果,1到40个回调函数分别被执行。

thread_pool:C ++线程池库 线程池 ThreadPool是仅c ++头文件库,用于修改和扩展 。 用法 要构建thread_pool,请运行以下命令: git clone https://github.com/rvaser/thread_pool && cd thread_pool && mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release .. && make 这将创建安装目标和单元测试。 运行make install将在您的系统上创建一个程序包,该程序包可通过以下方式搜索和链接: find_package (thread_pool) target_link_libraries (<target> thread_pool:thread_pool) 另一方面,您可以将thread_pool包含为子模块,并使用以下命令将其添加到您的项目中: i 立即下载

相关推荐

threadpool 线程池 C语言版

C语言版现成池 任务队列 可扩展为线程组

简单Linux C线程池的实现

转载自http://www.cnblogs.com/venow/archive/2012/11/22/2779667.html 大多数的网络服务器,包括Web服务器都具有一个特点,就是单位时间内必须处理数目巨大的连接请求,但是处理时间却是比较短的。在传统的多线程服务器模型中是这样实现的:一旦有个请求到达,就创建一个新的线程,由该线程执行任务,任务执行完毕之后,线程就退出。这就是"即时创建

nkguohao的专栏 1034

cpp-threadpool一个C语言栈式线程池

特性 动态扩展、缩减线程池规模

c语言实现一个线程池

C语言实现线程池

samllchinck的博客 184

线程池 threadPool c语言实现

保存的一份Linux下的线程池代码,使用C语言编写,另外添加了较详细的中文注释,附带测试代码,可以加深一些对线程池的认识,居家必备

threadpool

threadpool实现方式 threadpool实现方式 threadpool实现方式

C语言线程池

线程池什么是线程池为什么要使用线程池线程池的工作流程图任务队列线程池的创建线程池的初始化工作者添加任务线程池的销毁完整代码threadpool.hpthreadpool.c总结 什么是线程池 线程池就是一个容纳多个线程的容器,对于一线线程我们可以多次对此线程进行重复使用,从而省去频繁创建线程对象的操作。 为什么要使用线程池 频繁的进行进程的创建与销毁将带来很多开销。不但如此,进程间频繁的切换也将减低 CPU 的利用率。 如果能复用之前创建的进程,而不是为每个并发任务创建一个进程,能有效降低进程创建与销毁的开

m0_61705102的博客 4470

Livox-avia+FAST-LIO麻瓜使用教程

激光雷达 SLAM Fastlio 安装

aaaaaaaaaww12的博客 3675

C 线程池 thread_pool

#ifndef THREAD_POOL_H #define THREAD_POOL_H #include #include #include typedef void *(*process)(void *arg); typedef struct _thread_worker_t { process fun; void *arg; struct _thread_wo

nuptxiaoli 799

STM32CubeMx+stm32f407+FreeRTOS+LAN8720实现LWIP以太网UDP TCP数据收发功能

单片机实现LWIP的调试

qq_40600203的博客 3068

Windows Server 2012评估版过期自动关机问题:两种高效解决方案详解

本文针对Windows Server 2012评估版过期导致的自动关机问题,提供了两种高效解决方案。一是通过slmgr.vbs命令重置授权,临时延长评估期;二是使用DISM工具将评估版转换为正式版,一劳永逸。文章详细解析了两种方法的操作步骤、注意事项及适用场景,帮助用户快速恢复服务器稳定运行。

pytorchlight8的博客 1195

【Linux】多线程 -> 使用C/C++实现简单的线程池

使用C和C++实现了线程池的基本设计......

2202_75924820的博客 1082

CST-Python(Pycharm如何与CST联合仿真,获取S参数)

我们想使用Python与CST联合仿真,其实是不需要自己下载Python的,因为CST在下载的时候就自带了Python3.6,我们只需要找到并将软件的环境设置到相应位置,即可联合仿真。(我的保存路径为D:\Program Files (x86)\CST Studio Suite 2020,在寻找时可以将前面切换成自己的保存路径,后面不需要修改)在CST帮助文档(打开CST软件,按F11即可直接访问帮助文档)里面,进行如下操作,便可以看到CST适配的Python版本为Python3.6!

weixin_52696285的博客 5648

linux C 简单线程池实现_linux自实现c线程池

/ 队头 -> 取数据。// 队尾 -> 放数据。// 工作的线程(消费者线程)任务函数。// 获取线程池中工作的线程的个数。// 获取线程池中活着的线程的个数。// 创建线程池并初始化。// 管理者线程任务函数。//每次添加的线程数量。// 给线程池添加任务。// 每隔3s检测一次。// 阻塞生产者线程。

2401_88972089的博客 624

14003.xilinx系统移植

文章目录1 xilinx 系统移植 sd卡版本1.1 创建项目1.2 拷贝 *.hdf 到工程目录1.3 根据hdf文件对系统进行配置1.3.1 设置内核源码路径为本地1.3.2 设置分区的名称与大小1.4 清除本地缓存并编译成功1.5 打包生成BOOT.BIN并拷贝到sd卡1.6 问题1.7 系统启动成功1.8 配置设备树文件丰富系统外设 1 xilinx 系统移植 sd卡版本 芯片型号 ZYNQ UltraScale+ XAZU2EG ,对应厂家提供的demo板为 zu102或zu104 1.1 创建

写给自己的笔记 481

Python 爬虫实战:抓取应届生求职网校招岗位信息,助力学子就业

应届生求职网作为国内知名的招聘平台,汇聚了大量企业的校招岗位信息。了解这些岗位信息,对于应届毕业生制定求职策略、企业制定招聘计划以及相关就业市场分析等都具有重要意义。因此,本文将深入探讨如何运用 Python 爬虫技术从应届生求职网平台抓取校招岗位信息,为应届毕业生提供有益的就业信息支持。本文深入探究了利用 Python 爬虫技术从应届生求职网平台抓取校招岗位信息的全流程。从前期的环境搭建、模拟登录,到核心的数据抓取、存储,再到后续的数据分析与可视化,都详细展开讲解并提供代码支持。

u014481728的博客 1300

线程池 c linux 编程,Linux C 实现一个简单的线程池

线程池的定义线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但...

weixin_35679132的博客 114

QNX侧触摸屏(TP)Bringup流程与源码深度解析

QNX侧TP Bringup的核心在于构建。

QQ_778132974的博客 477

linux C 简单线程池实现

线程过多会带来额外的开销,其中包括创建销毁线程的开销、调度线程的开销等等,同时也降低了计算机的整体性能。线程池维护多个线程,等待监督管理者分配可并发执行的任务。这种做法,一方面避免了处理任务时创建销毁线程开销的代价,另一方面避免了线程数量膨胀导致的过分调度问题,保证了对内核的充分利用。...

快乐小半半的博客 580

ChatGPT辅助课题申报书研究背景部分的写作全过程指南

ChatGPT辅助课题申报书研究背景部分的写作全过程指南

智能AI让学术科研更容易 2554

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

一个linux下c线程池的实现,Linux C线程池简单实现实例

Linux C线程池三个文件1 tpool.htypedef struct tpool_work {void (*routine)(void *);void *arg;struct tpool_work *next;} tpool_work_t;typedef struct tpool {/* pool characteristics */int nu...

weixin_36002475的博客 188

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Linux 下C语言简单实现线程池

转自:http://blog.youkuaiyun.com/wallwind/article/details/7669132 C语言简单实现线程池 0 前言 网上关于线程池的例子还是不少,简单明了的倒是比较少,看了网上的资料,打算借鉴网上的一些例子,自己实现以下。 线程的概念就不多说,首先说一下多线程的好处:多线程技术主要解决处理器单元内多个线程执行的问题,它可

dyf20081124的专栏 536

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

ssm框架搭建

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

基于linux下c实现的简单版线程池

【代码】基于linux下c实现的简单版线程池。

weixin_72492465的博客 370
上一篇: pthread_cond_init,pthread_cond_wait
下一篇: C 宏定义实现字符大小写转换
pingd
博客等级 码龄15年 60粉丝 54原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值