linux之线程池

1. 简介

• 线程池是一种用于管理和重用多个线程的设计模式 。它通过维护一个线程池(线程的集合),可以有效地处理并发任务而无需每次都创建和销毁线程 。这种方法可以减少线程创建和销毁的开销,提高性能和资源利用率。 提高响应速度,任务来了直接交给空闲线程执行,无需等待线程创建。

2. Glib的工作流程

• 线程池创建:首先创建一个线程池,指定任务函数和其他参数 。线程池会创建一定数量的线程,这些线程进入等待状态,准备执行任务,或在提交任务后才创建线程(取决于配置)。线程池中的所有线程执行的都是同一个任务函数。

• 任务队列:线程池维护一个任务队列。当我们向线程池提交任务时,任务会被放入这个队列中 。实际上,放入任务队列 的是 我们在提交任务时传递的任务数据。

• 线程执行任务:线程池中的线程从任务队列中取出任务数据,然后调用任务函数,执行任务。执行完成后,线程不会退出,而是继续从任务队列中取下一个任务执行。如果没有待执行的任务,线程通常在等待一段时间后被回收(取决于具体的配置)。

3. 相关函数

3.1 GFunc

cpp 复制代码
// 此处的 data 是在启动任务时,传递给每个任务的,而 user_data 是在创建线程池时传入的共享数据,对于每个任务都是一样的 
typedef void (*GFunc)(gpointer data, gpointer user_data);

3.2 g_thread_pool_new

cpp 复制代码
/** 
* @brief 创建新的线程池 
* 
* @param func 池中线程执行的函数 
* @param user_data 传递给 func 的数据,可以为 NULL,这里的 user_data 最终会被存储在 GThreadPool 结构体的 user_data 属性中 
* @param max_threads 线程池容量,即当前线程池中可以同时运行的线程数。-1 表示没有限制 
* @param exclusive 独占标记位。决定当前的线程池独占所有的线程 还是与其它线程池共享这些线程。取值可以是 TRUE 或 FALSE 
* TRUE:立即启动数量为 max_threads 的线程,且启动的线程只能被当前线程池使用 
* FALSE:只有在需要时,即需要执行任务时才创建线程,且线程可以被多个非独享资源的线程池共用 
* @param error 用于报告错误信息,可以是 NULL,表示忽略错误 
* @return GThreadPool* 线程池实例指针。无论是否发生错误,都会返回有效的线程池 
*/ 
GThreadPool *g_thread_pool_new( 
	GFunc func, 
	gpointer user_data, 
	gint max_threads, 
	gboolean exclusive, 
GError **error);

3.3 g_thread_pool_push

cpp 复制代码
/** 
* @brief 向 pool 指向的线程池实例添加数据,这一行为实际上会向任务队列添加新的任务。当存在可用线程时任务立即执行,否则任务数据会一直待在队列中,直至腾出可用线程执行任务 
* 
* @param pool 指向线程池实例的指针 
* @param data 传递给每个任务的独享数据 
* @param error 错误信息 
* @return gboolean 成功返回 TRUE,失败返回 FALSE 
*/ 
gboolean g_thread_pool_push( 
	GThreadPool *pool, 
	gpointer data, 
GError **error);

3.4 g_thread_pool_free

cpp 复制代码
/** 
* @brief 释放为 pool 指向的线程池分配的所有资源 
* 
* @param pool 线程池指针 
* @param immediate 是否立即释放线程池 
* TRUE:立即释放所有资源,未处理的数据不被处理 
* FALSE:在最后一个任务执行完毕之前,线程池不会被释放 
* 需要注意的是:执行任务时,线程池的任何一个线程都不会被打断。无论这个参数是何取值,都可以保证至少线程池释放前正在运行的线程可以完成它们的任务。 
* @param wait_ 当前函数是否阻塞等待 所有任务完成 
* TRUE:所有需要处理的任务执行完毕当前函数才会返回 
* FALSE:当前函数立即返回 
*/ 
void g_thread_pool_free ( 
	GThreadPool* pool, 
	gboolean immediate, 
	gboolean wait_ 
);

3.5 例子

cpp 复制代码
#include <glib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>


void task(gpointer data,gpointer user_data){
    int tmp = *((int *)data);//每个任务独享的数据。
    free(data);
    printf("任务%d开始执行\n",tmp);
    sleep(tmp);
    printf("任务%d执行结束\n",tmp);
}

int main(int argc, char const *argv[])
{
    //创建线程池
    GThreadPool * gtp = g_thread_pool_new(task,NULL,5,TRUE,NULL);

    //提交任务10个
    for (size_t i = 0; i < 10; i++)
    {
        int * tmp = malloc(sizeof(int));
        *tmp =  i + 1;
        g_thread_pool_push(gtp,tmp,NULL);
    }
    
    //释放线程池
    g_thread_pool_free(gtp,FALSE,TRUE);
    printf("所有任务都执行完成了\n");
    return 0;
}

• 结果,如图:

相关推荐
夜听莺儿鸣8 小时前
502-003_Linux 中断与异常(一):从Linux角度理解中断与异常
linux·中断与异常·linux中断
杨云龙UP8 小时前
TDengine 3.4.2.8 Community 三节点三副本生产集群部署实战(DNode/MNode/taosAdapter/Explorer)
大数据·linux·运维·数据库·tdengine·时序库
向成科技9 小时前
XC3576H工控主板|深度适配Ubuntu 26.04 LTS,释放边缘AI与工业开发新潜能
linux·人工智能·ubuntu·机器人·硬件·主板·边缘ai
Fcy64810 小时前
Linux下 进程间关系与守护进程
linux·运维·服务器·守护进程
码农小韩10 小时前
Linux驱动理论(二)——Linux字符设备驱动
linux·嵌入式软件开发·linux操作系统·linux应用开发·linux驱动理论
well061210 小时前
Linux粘滞位与Makefile机制深度解析
linux·运维·服务器
再写一行代码就下班10 小时前
linux sh脚本在windows修改导致无法使用解决方式
java·linux·centos
额额额对了11 小时前
SPI通信
linux·c语言·汇编·单片机·嵌入式硬件·arm
子木HAPPY阳VIP11 小时前
Ubuntu 关闭防火墙操作步骤
linux·运维·ubuntu
王振超wzc11 小时前
嵌入式开发环境搭建--WM软件安装,Ubuntu操作系统安装
linux·运维·ubuntu