线程池代码(通用版)
2023-09-11 14:14:05 时间
一、适用场景
首先,必须明确一点,线程池不是万能的,它有其特定的使用场景。使用线程池是为了减小线程本身的开销对应用性能所产生的影响,但是其 前提是线程本身创建、销毁的开销和线程执行任务的开销相比是不可忽略的 。如果线程本身创建、销毁的开销对应用程序的性能可以忽略不计,那么使用/不使用线程池对程序的性能并不会有太大的影响。
线程池通常适合以下几种场景:
①、单位时间内处理的任务频繁,且任务时间较短
②、对实时性要求较高。如果接收到任务之后再创建线程,可能无法满足实时性的要求,此时必须使用线程池。
③、必须经常面对高突发性事件。比如Web服务器。如果有足球转播,则服务器将产生巨大冲击,此时使用传统方法,则必须不停的大量创建、销毁线程。此时采用动态线程池可以避免这种情况的发生。
二、代码实现
2.1 头文件
#if !defined(__THREAD_POOL_H__) #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <memory.h> #include <pthread.h> #include <sys/types.h> // 布尔类型 typedef int bool; #define false (0) #define true (1) /* 线程任务链表 */ typedef struct _thread_worker_t { void *(*process)(void *arg); /* 线程处理的任务 */ void *arg; /* 任务接口参数 */ struct _thread_worker_t *next;/* 下一个节点 */ }thread_worker_t; /* 线程池对象 */ typedef struct { pthread_mutex_t queue_lock; /* 队列互斥锁 */ pthread_cond_t queue_ready; /* 队列条件锁 */ thread_worker_t *head; /* 任务队列头指针 */ bool isdestroy; /* 是否已销毁线程 */ pthread_t *threadid; /* 线程ID数组 —动态分配空间 */ int num; /* 线程个数 */ int queue_size; /* 工作队列当前大小 */ }thread_pool_t; /* 函数声明 */ extern int thread_pool_init(thread_pool_t **pool, int num); extern int thread_pool_add_worker(thread_pool_t *pool, void *(*process)(void *arg), void *arg); extern int thread_pool_destroy(thread_pool_t *pool); #endif /*__THREAD_POOL_H__*/
2.2 函数实现
/************************************************************* **功 能:线程池的初始化 **参 数: ** pool:线程池对象 ** num :线程池中线程个数 **返回值:0:成功 !0: 失败 *************************************************************/ int thread_pool_init(thread_pool_t **pool, int num) { int idx = 0; /* 为线程池分配空间 */ *pool = (thread_pool_t*)calloc(1, sizeof(thread_pool_t)); if(NULL == *pool) { return -1; } /* 初始化线程池 */ pthread_mutex_init(&((*pool)->queue_lock), NULL); pthread_cond_init(&((*pool)->queue_ready), NULL); (*pool)->head = NULL; (*pool)->num = num; (*pool)->queue_size = 0; (*pool)->isdestroy = false; (*pool)->threadid = (pthread_t*)calloc(1, num*sizeof(pthread_t)); if(NULL == (*pool)->threadid) { free(*pool); (*pool) = NULL; return -1; } /* 依次创建线程 */ for(idx=0; idx<num; idx++) { pthread_create(&((*pool)->threadid[idx]), NULL, thread_routine, *pool); } return 0; }
/************************************************************* **功 能:将任务加入线程池处理队列 **参 数: ** pool:线程池对象 ** process:需处理的任务 ** arg: process函数的参数 **返回值:0:成功 !0: 失败 *************************************************************/ int thread_pool_add_worker(thread_pool_t *pool, void *(*process)(void *arg), void *arg) { thread_worker_t *worker=NULL, *member=NULL; worker = (thread_worker_t*)calloc(1, sizeof(thread_worker_t)); if(NULL == worker) { return -1; } worker->process = process; worker->arg = arg; worker->next = NULL; pthread_mutex_lock(&(pool->queue_lock)); member = pool->head; if(NULL != member) { while(NULL != member->next) member = member->next; member->next = worker; } else { pool->head = worker; } pool->queue_size++; pthread_mutex_unlock(&(pool->queue_lock)); pthread_cond_signal(&(pool->queue_ready)); return 0; }
/************************************************************* **功 能:线程池的销毁 **参 数: ** pool:线程池对象 **返回值:0:成功 !0: 失败 *************************************************************/ int thread_pool_destroy(thread_pool_t *pool) { int idx = 0; thread_worker_t *member = NULL; if(false != pool->isdestroy) { return -1; } pool->isdestroy = true; pthread_cond_broadcast(&(pool->queue_ready)); for(idx=0; idx<pool->num; idx++) { pthread_join(pool->threadid[idx], NULL); } free(pool->threadid); pool->threadid = NULL; while(NULL != pool->head) { member = pool->head; pool->head = member->next; free(member); } pthread_mutex_destroy(&(pool->queue_lock)); pthread_cond_destroy(&(pool->queue_ready)); free(pool); return 0; }
/************************************************************* **功 能:线程池各个线程入口函数 **参 数: ** arg:线程池对象 **返回值:0:成功 !0: 失败 *************************************************************/ static void *thread_routine(void *arg) { thread_worker_t *worker = NULL; thread_pool_t *pool = (thread_pool_t*)arg; while(1) { pthread_mutex_lock(&(pool->queue_lock)); while((false == pool->isdestroy) && (0 == pool->queue_size)) { pthread_cond_wait(&(pool->queue_ready), &(pool->queue_lock)); } if(false != pool->isdestroy) { pthread_mutex_unlock(&(pool->queue_lock)); pthread_exit(NULL); } pool->queue_size--; worker = pool->head; pool->head = worker->next; pthread_mutex_unlock(&(pool->queue_lock)); /* 执行队列中的任务 */ (*(worker->process))(worker->arg); free(worker); worker = NULL; } }
学习版:https://www.cnblogs.com/cthon/p/9085026.html
通用版代码:https://www.cnblogs.com/cthon/p/9097007.html
难度升级版代码:https://www.cnblogs.com/cthon/p/9085623.html
相关文章
- 线程管理(四)操作线程的中断机制
- 16 线程池 代码:测试线程池
- 10 线程状态 线程状态观测 概念 代码:观察测试线程的状态 线程优先级 代码:测试线程的优先级 守护(daemon)线程 代码:测试守护线程
- 09 线程状态 线程礼让 概念 代码:测试礼让线程 Join 代码:测试join方法
- 《代码整洁之道》—第13章13.9节测试线程代码
- C++实现线程安全的单例模式
- Java 线程池之FixedThreadPool(Java代码实战-003)
- Java多线程理解:线程安全的集合对象
- 线程状态与控制结构
- linux下使用线程锁互斥访问资源
- Java学习-082-多线程15:线程中断退出
- Java学习-078-多线程11:使用 synchronized 同步代码块解决线程资源同步问题
- Java学习-072-多线程05:线程休眠 Thread.sleep()
- 关于C#中Queue的线程安全问题
- 浅析JavaScript中的协程、进程如何切换线程的机制、线程如何切换协程的机制、协程的体现(生成器函数)、协程如何实现异步和非阻塞以及为什么要使用生成器+Promise组合
- JUC多线程:创建线程的四种方式
- Linux下如何查看高CPU占用率线程
- 29初识线程2
- springmvc在使用@ModelAttribute注解获取Request和Response会产生线程并发不安全问题
- Java 线程池框架核心代码分析--转
- Java多线程基础(一)---Thread API(join深度详解、源码分析和案例分析之代码实现,优雅关闭线程三种方式)