线程池见解
1.消息队列
2.线程池见解
线程池
线程池是一种用于管理和优化多线程应用程序性能的设计模式。它预先创建一组线程,并将任务分配给这些线程执行,从而减少了创建和销毁线程的开销,提高了系统的效率和响应速度。
线程池的基本概念
- 线程池:一个包含多个线程的集合,这些线程可以被重复使用来执行多个任务。
- 任务队列:一个存储等待执行任务的队列。当有新的任务到来时,它们会被添加到这个队列中。
- 工作线程:线程池中的线程,这些线程会不断从任务队列中取出任务并执行。
- 线程池管理器:负责管理线程池的生命周期,包括线程的创建、销毁和任务的分配。
线程池的优点
- 减少线程创建和销毁的开销:线程的创建和销毁是昂贵的操作。线程池通过重用线程减少了这些开销。
- 提高响应速度:当任务到来时,不需要等待线程创建,可以立即使用线程池中的空闲线程执行任务。
- 控制并发量:可以通过限制线程池中的最大线程数来控制系统的并发量,防止资源耗尽。
- 统一管理:线程池提供了一个统一的管理接口,可以更方便地监控和调优线程的使用。
线程池的实现原理
线程池的实现通常包括以下几个部分:
-
线程池初始化:创建一个固定数量的线程并将它们放入线程池中。
-
任务提交:提供一个接口,将任务添加到任务队列中。
-
任务调度:线程池中的工作线程不断从任务队列中取出任务并执行。
-
线程管理:根据系统负载动态调整线程池的大小(可选)。
线程示意图
以下是一个示意图,展示了线程池的基本结构和工作流程:
+-------------------------+
| Thread Pool |
| |
| +-------------------+ |
| | Worker Thread | |
| | (Thread 1) | |
| +-------------------+ |
| |
| +-------------------+ |
| | Worker Thread | |
| | (Thread 2) | |
| +-------------------+ |
| |
| +-------------------+ |
| | Worker Thread | |
| | (Thread 3) | |
| +-------------------+ |
| |
| +-------------------+ |
| | Worker Thread | |
| | (Thread 4) | |
| +-------------------+ |
| |
+-------------------------+
+-------------------------+
| Task Queue |
| |
| +-------------------+ |
| | Task 1 | |
| +-------------------+ |
| |
| +-------------------+ |
| | Task 2 | |
| +-------------------+ |
| |
| +-------------------+ |
| | Task 3 | |
| +-------------------+ |
| |
| +-------------------+ |
| | Task 4 | |
| +-------------------+ |
| |
+-------------------------+
图片说明
- 线程池 (Thread Pool):
- 包含多个工作线程(Worker Thread),如图中的 Thread 1 到 Thread 4。
- 这些工作线程在创建后会一直存在,并等待任务的到来。
- 任务队列 (Task Queue):
- 存储待执行的任务,如图中的 Task 1 到 Task 4。
- 当有新的任务到来时,它们会被添加到这个队列中。
工作流程
- 任务提交:
- 新的任务被提交到任务队列中。
- 任务分配:
- 线程池中的工作线程不断地从任务队列中取出任务并执行。
- 每个工作线程在完成当前任务后,会继续从队列中取出下一个任务,直到任务队列为空。
- 任务执行:
- 工作线程执行任务函数,并处理任务参数。
- 线程重用:
- 工作线程在完成任务后不会被销毁,而是继续等待新的任务到来,从而实现线程的重用。
优点
- 减少线程创建和销毁的开销:通过重用线程,减少了频繁创建和销毁线程的开销。
- 提高响应速度:任务可以立即由空闲线程执行,而不需要等待新线程的创建。
- 控制并发量:通过限制线程池中的最大线程数,控制系统的并发量,防止资源耗尽。
线程池的基本操作
线程池相关头文件,宏定义以及结构体,包含线程池的所有状态信息,包括线程数组、任务队列、锁和条件变量
/****************************************************************
*
* name : threadpool
* function : 创建一个线程池,其中有四个线程,将任务分配给线程,完成任务可以回收线程,也可以添加线程,也可以销毁线程
* argument :
* retval : None
* author : yq_dyx@163.com
* date : 2024/06/11
* note : None
*
****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define MAX_THREADS 4 // 线程池中的最大线程数
#define MAX_QUEUE 10 // 任务队列的最大大小
// 定义任务结构体
typedef struct {
void (*function)(void*); // 任务函数指针
void* argument; // 任务函数参数
} task_t;
// 定义线程池结构体
typedef struct {
pthread_mutex_t lock; // 互斥锁
pthread_cond_t notify; // 条件变量
pthread_t threads[MAX_THREADS]; // 线程数组
task_t queue[MAX_QUEUE]; // 任务队列
int queue_size; // 任务队列大小
int head; // 队列头索引
int tail; // 队列尾索引
int count; // 队列中任务计数
int shutdown; // 线程池关闭标志
} threadpool_t;
工作线程函数
线程池中每个线程执行的函数,从任务队列中取出任务并执行,如果线程池关闭,线程进入等待状态,如果线程池关闭,线程退出.
void* thread_do_work(void* arg) {
threadpool_t* pool = (threadpool_t*)arg; // 获取线程池指针
task_t task;
while (1) {
pthread_mutex_lock(&(pool->lock)); // 加锁
// 等待任务队列中有任务或线程池关闭
while ((pool->count == 0) && (!pool->shutdown)) {
pthread_cond_wait(&(pool->notify), &(pool->lock));
}
// 如果线程池关闭,退出线程
if (pool->shutdown) {
pthread_mutex_unlock(&(pool->lock));
pthread_exit(NULL);
}
// 从任务队列中取出任务
task.function = pool->queue[pool->head].function;
task.argument = pool->queue[pool->head].argument;
pool->head = (pool->head + 1) % MAX_QUEUE;
pool->count -= 1;
pthread_mutex_unlock(&(pool->lock)); // 解锁
// 执行任务
(*(task.function))(task.argument);
}
pthread_exit(NULL);
return NULL;
}
线程池创建函数
- 初始化线程池结构体。
- 初始化互斥锁和条件变量。
- 创建工作线程
// 创建线程池
threadpool_t* threadpool_create() {
threadpool_t* pool = (threadpool_t*)malloc(sizeof(threadpool_t));
if (pool == NULL) {
return NULL; // 分配内存失败
}
pool->queue_size = MAX_QUEUE;
pool->head = pool->tail = pool->count = 0;
pool->shutdown = 0;
// 初始化互斥锁和条件变量
pthread_mutex_init(&(pool->lock), NULL);
pthread_cond_init(&(pool->notify), NULL);
// 创建工作线程
for (int i = 0; i < MAX_THREADS; i++) {
pthread_create(&(pool->threads[i]), NULL, thread_do_work, (void*)pool);
}
return pool;
}
添加任务函数
- 向任务队列中添加任务。
- 如果任务队列已满,返回错误。
- 通知工作线程有新任务。
// 向线程池添加任务
int threadpool_add(threadpool_t* pool, void (*function)(void*), void* argument) {
pthread_mutex_lock(&(pool->lock)); // 加锁
int next = (pool->tail + 1) % pool->queue_size;
// 如果任务队列已满,返回错误
if (pool->count == pool->queue_size) {
pthread_mutex_unlock(&(pool->lock));
return -1; // 任务队列已满
}
// 添加任务到任务队列
pool->queue[pool->tail].function = function;
pool->queue[pool->tail].argument = argument;
pool->tail = next;
pool->count += 1;
// 通知工作线程有新任务
pthread_cond_signal(&(pool->notify));
pthread_mutex_unlock(&(pool->lock)); // 解锁
return 0;
}
销毁线程池函数
- 设置关闭标志,通知所有工作线程。
- 等待所有工作线程结束。
- 销毁互斥锁和条件变量,释放线程池内存。
// 销毁线程池
void threadpool_destroy(threadpool_t* pool) {
pthread_mutex_lock(&(pool->lock)); // 加锁
pool->shutdown = 1; // 设置关闭标志
pthread_cond_broadcast(&(pool->notify)); // 通知所有工作线程
pthread_mutex_unlock(&(pool->lock)); // 解锁
// 等待所有工作线程结束
for (int i = 0; i < MAX_THREADS; i++) {
pthread_join(pool->threads[i], NULL);
}
// 销毁互斥锁和条件变量
pthread_mutex_destroy(&(pool->lock));
pthread_cond_destroy(&(pool->notify));
free(pool); // 释放线程池内存
}
示例任务函数
模拟任务执行,打印任务信息并休眠1秒
// 示例任务函数
void example_task(void* arg) {
int num = *(int*)arg;
printf("Thread %lu is working on task %d\n", pthread_self(), num);
sleep(1); // 模拟任务执行时间
}
主函数
- 创建线程池。
- 向线程池添加任务。
- 等待所有任务完成。
- 销毁线程池。
int main() {
// 创建线程池
threadpool_t* pool = threadpool_create();
if (pool == NULL) {
fprintf(stderr, "Failed to create thread pool\n");
return 1;
}
// 向线程池添加任务
int tasks[20];
for (int i = 0; i < 20; i++) {
tasks[i] = i;
threadpool_add(pool, example_task, (void*)&tasks[i]);
}
sleep(5); // 等待所有任务完成
threadpool_destroy(pool); // 销毁线程池
return 0;
}
代码详细说明
- 任务结构体
task_t
:function
:指向任务函数的指针。argument
:任务函数的参数。
- 线程池结构体
threadpool_t
:lock
:互斥锁,用于保护共享资源。notify
:条件变量,用于通知工作线程有新任务到来。threads
:线程数组,存储线程池中的线程。queue
:任务队列,存储待执行的任务。queue_size
:任务队列的大小。head
:任务队列的头索引。tail
:任务队列的尾索引。count
:任务队列中的任务计数。shutdown
:线程池关闭标志。
- 工作线程函数
thread_do_work
:- 从任务队列中取出任务并执行。
- 如果任务队列为空且线程池未关闭,线程进入等待状态。
- 如果线程池关闭,线程退出。
- 线程池创建函数
threadpool_create
:- 初始化线程池结构体。
- 初始化互斥锁和条件变量。
- 创建工作线程。
- 添加任务函数
threadpool_add
:- 向任务队列中添加任务。
- 如果任务队列已满,返回错误。
- 通知工作线程有新任务。
- 销毁线程池函数
threadpool_destroy
:- 设置关闭标志,通知所有工作线程。
- 等待所有工作线程结束。
- 销毁互斥锁和条件变量,释放线程池内存。
- 示例任务函数
example_task
:- 模拟任务执行,打印任务信息并休眠1秒。
- 主函数
main
:- 创建线程池。
- 向线程池添加任务。
- 等待所有任务完成。
- 销毁线程池。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!