线程池学习路径:www.bilibili.com,侵联删。
1、线程池的设计
程序中,频繁地调用pthread_create函数创建线程,非常浪费时间,尤其在服务器端的时候,多线程的使用情况下频繁启用线程和释放线程资源,这样也会影响程序的运行效率。
我们可以先在服务器空闲的时候先创建多个线程,我们先在线程函数里面使用pthread_cond_wait将其休眠,有任务过来的时候使用pthread_cond_signal启用线程。
线程池需要下面的相关知识:
线程的相关api函数
条件变量
互斥锁(与条件变量结合使用)
任务队列(链队使用更方便)
队列相当于是一个共享变量,这些子线程会不断地取任务去执行,有任务出队有任务入队,同一个时刻只能有一个任务进行操作。条件变量用来控制线程的睡眠、启动和销毁时机。
2、c语言实现简易线程池
threadpool.h
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
// queue node
typedef struct Task
{
void (*function)(void *arg);
void *arg;
struct Task *next;
} Task;
typedef struct ThreadPool
{
Task *queueFront;
Task *queueRear;
int num;
pthread_t *threadID;
pthread_mutex_t mutex;
pthread_cond_t cond;
// shutdown pool
int shutdown;
} ThreadPool;
threadpool.c
#include "threadpool.h"
void *worker(void *arg)
{
ThreadPool *pool = (ThreadPool *)arg;
while (1)
{
pthread_mutex_lock(&pool->mutex);
// 如果任务队列为空,且线程池没有被关闭,线程睡眠
while (pool->queueFront == pool->queueRear && pool->shutdown == 0)
{
// 阻塞等待任务
pthread_cond_wait(&pool->cond, &pool->mutex);
}
if (pool->shutdown == 1) {
printf("--------------------debug8");
pthread_mutex_unlock(&pool->mutex);
printf("thread shutdown thread %ld exit ...\n", pthread_self());
pthread_exit((void *)0);
}
Task task;
Task *t = pool->queueFront->next;
task.function = t->function;
task.arg = t->arg;
pool->queueFront->next = t->next;
free(t);
if (pool->queueFront->next == NULL) {
pool->queueRear = pool->queueFront;
}
pthread_mutex_unlock(&pool->mutex);
printf("thread %ld start working ...\n", pthread_self());
task.function(task.arg); // 函数指针调用函数
printf("thread %ld end working ...\n", pthread_self());
}
}
ThreadPool *create_thread_pool(int num)
{
// printf("--------------------debug1");
ThreadPool *pool = (ThreadPool *)malloc(sizeof(ThreadPool));
if (pool == NULL) {
printf("malloc threadpool memory failed\n");
return NULL;
}
// printf("--------------------debug2");
pool->queueFront = (Task *)malloc(sizeof(Task));
if (pool->queueFront == NULL) {
fprintf(stderr, "malloc Task failed\n");
goto pfree;
return NULL;
}
// printf("--------------------debug3");
// pool->queueRear = pool->queueFront;
pool->queueFront->next = NULL;
pool->queueRear = pool->queueFront;
pool->num = num;
// printf("--------------------debug4");
// init threadid
pool->threadID = (pthread_t *)malloc(sizeof(pthread_t) * num);
if (pool->threadID == NULL) {
fprintf(stderr, "malloc threadID failed\n");
goto qfree;
return NULL;
}
// printf("--------------------debug5");
for (int i = 0; i < num; i++) {
if (pthread_create(&pool->threadID[i], NULL, worker, pool) != 0)
{
fprintf(stderr, "pthread_create threadID failed\n");
goto tfree;
return NULL;
}
pthread_detach(pool->threadID[i]); // pthread detach
}
// printf("--------------------debug6");
pthread_mutex_init(&pool->mutex, NULL);
pthread_cond_init(&pool->cond, NULL);
pool->shutdown = 0; // 0: running 1: shutsown
return pool;
pfree:
free(pool);
return 0;
qfree:
free(pool->queueFront);
free(pool);
return 0;
tfree:
free(pool->threadID);
free(pool->queueFront);
free(pool);
return 0;
}
void taskfunction(void *arg)
{
int num = *(int *)arg;
printf("thread %ld is working num = %d ...\n", pthread_self(), num);
sleep(1);
free(arg);
// return 0;
}
void thread_pool_add(ThreadPool *pool, void (*func)(void *), void *arg)
{
pthread_mutex_lock(&pool->mutex);
Task *t = (Task *)malloc(sizeof(Task));
if (t == NULL) {
fprintf(stderr, "malloc Task failure\n");
return;
}
// 一个任务包含三个部分,线程函数,参数,指向下一个任务节点的指针
t->function = func;
t->arg = arg;
t->next = NULL;
pool->queueRear->next = t;
pool->queueRear = t;
pthread_mutex_unlock(&pool->mutex);
pthread_cond_signal(&pool->cond);
}
void thread_pool_destroy(ThreadPool *pool)
{
// 关闭线程池
pool->shutdown = 1;
printf("--------------------debug7");
// 唤醒所有线程
for (int i = 0; i < pool->num; i++) {
pthread_cond_signal(&pool->cond);
}
// 释放线程号
if (pool->threadID) {
free(pool->threadID);
}
// 释放任务队列
while (pool->queueFront->next)
{
Task *t = pool->queueFront->next;
pool->queueFront->next = t->next;
free(t);
}
free(pool->queueFront);
// 释放互斥锁和条件变量
pthread_mutex_destroy(&pool->mutex);
pthread_cond_destroy(&pool->cond);
// 释放线程池
free(pool);
}
int main()
{
ThreadPool *pool = create_thread_pool(10);
if (pool == NULL) {
printf("create thread pool failed\n");
return -1;
}
printf("threadPool create success.\n");
sleep(1);
for (int i = 0; i < 50; i++) {
int *n = (int *)malloc(sizeof(int));
*n = i;
// 将任务添加到任务队列,taskfunction任务函数
thread_pool_add(pool, taskfunction, n);
}
sleep(6);
thread_pool_destroy(pool);
return 0;
}