一. 线程池原理
线程池是一种多线程的处理方式,处理方法是将“生产者”线程提出的任务添加到“任务队列”,然后创建一些线程自动去完成“任务队列”上面的任务,可以降低频繁创建和销毁线程带来的实际开销
线程池技术思路如下:"任务队列"是一个共享资源,“互斥访问”一般采用预创建线程技术,也就是在应用启动的时候就创建一定数量的线程
线程固定的执行一个“任务调配函数”,当“任务队列”没有任务的时候,线程自动的休眠(等待一个条件),当任务到来的时候,被唤醒,执行任务
线程完成任务后不会被销毁,而是自动的执行任务队列的下一个任务
当任务太多的时候,增加一些线程数量,当任务太少的时候,销毁一些线程
二. 代码实现
threadpool.h
#ifndef __THREADPOOL_H__ #define __THREADPOOL_H__ #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define info_err(format, ...) { \ printf(format, __VA_ARGS__); \ perror(""); \ } // 线程处理函数 typedef void (*threadHand_t) (void *); // 事件队列结构体 typedef struct task { threadHand_t func; void *arg; } Task; // 线程池结构体 typedef struct threadpool { // 事件队列 Task *taskQueue; // 顺序队列 int QSize; // 队列的最大元素个数 int QNum; // 队列中的事件个数 int QFront; // 队头 int QRear; // 队尾 // 线程池信息 pthread_t managerID; // 管理者线程ID pthread_t *threadID; // 消费者线程ID int MAXThreadNum; // 最大线程数量 int MINThreadNum; // 最小线程数量 int busyThreadNum; // 工作的线程 int liveThreadNum; // 活着的线程 int exitThreadNum; // 需要销毁的线程数量 pthread_mutex_t mutexPool; // 整个线程池的线程锁 pthread_mutex_t mutexBusy; // 忙线程的线程锁 pthread_cond_t notFull; // 事件队列不满 pthread_cond_t notEmpty; // 事件队列非空 // 线程池状态 0 表示使用 1表示销毁 int shutdown; } ThreadPool; // 创建线程池 并初始化 ThreadPool* threadPoolInit(int min, int max, int size); // 销毁线程池 int threadPoolDestroy(ThreadPool *pool); // 给线程池 添加任务 void threadPoolAdd(ThreadPool *pool, threadHand_t func, void *arg); // 获取线程池中 工作的线程个数 int threadPoolBusyNum(ThreadPool *pool); // 获取线程池中 活着的线程个数 int threadPoolAliveNum(ThreadPool *pool); // 管理线程 void *manager(void *arg); // 工作线程 void* work(void *arg); // 线程退出函数 void threadExit(ThreadPool *pool); #endif
threadpool.c
#include "threadpool.h" const int CHANGENUM = 2; // 一次最多增加的消费者线程数量 // 创建线程池 并初始化 /* min: 最小线程数--核心线程数量 max: 最大线程数 size: 任务队列的最大元素个数 */ ThreadPool* threadPoolInit(int min, int max, int size) { // 定义一个线程池结构体指针 ThreadPool *threadPool = NULL; do { // 给线程池空间分配 threadPool = malloc(sizeof(ThreadPool)); if (threadPool == NULL) { perror("threadPool malloc fail"); break; } /* 线程池事件队列初始化 */ threadPool->taskQueue = malloc(sizeof(Task) * size); if (threadPool->taskQueue == NULL) { perror("taskQueue malloc fail"); break; } threadPool->QSize = size; // 队列的最大元素个数 threadPool->QNum = 0; // 队列中的事件个数 threadPool->QFront = threadPool->QRear = 0; // 对头、队尾 /* 线程池信息初始化 */ threadPool->MAXThreadNum = max; // 最大线程数量 threadPool->MINThreadNum = min; // 最小线程数量 // 消费者线程ID threadPool->threadID = malloc(sizeof(threadPool->threadID) * max); if (threadPool->threadID == NULL) { perror("threadID malloc fail"); break; } // 将消费者线程ID全部初始化为0 memset(threadPool->threadID, 0, sizeof(threadPool->threadID) * max); threadPool->liveThreadNum = min; // 活着的线程 threadPool->busyThreadNum = 0; // 工作的线程 threadPool->exitThreadNum = 0; // 需要销毁的线程数量 if (pthread_mutex_init(&threadPool->mutexPool, NULL) != 0 || pthread_mutex_init(&threadPool->mutexBusy, NULL) != 0 || pthread_cond_init(&threadPool->notFull, NULL) != 0 || pthread_cond_init(&threadPool->notEmpty, NULL) != 0) { printf("mutex or cond fail\n"); break; } /* 线程池状态 0 表示使用 1表示销毁 */ threadPool->shutdown = 0; // 创建一个管理者线程 管理者线程ID:threadPool->managerID pthread_create(&(threadPool->managerID), NULL, manager, threadPool); for (int i = 0; i < min; i++) { // 创建线程 线程池工作的最小线程 pthread_create(&(threadPool->threadID[i]), NULL, work, threadPool); } return threadPool; } while(0); if (threadPool && threadPool->threadID) { free(threadPool->threadID); } if (threadPool && threadPool->taskQueue) { free(threadPool->taskQueue); } if (threadPool) { free(threadPool); } return NULL; } // 销毁线程池 int threadPoolDestroy(ThreadPool *pool) { if (pool == NULL) { return -1; } // 关闭线程池 pool->shutdown = 1; // 阻塞回收管理者线程 pthread_join(pool->managerID, NULL); // 唤醒阻塞的消费者线程 for (int i = 0; i < pool->liveThreadNum; i++) { pthread_cond_signal(&pool->notEmpty); } // 释放堆内存 if (pool->taskQueue) { free(pool->taskQueue); } if (pool->threadID) { free(pool->threadID); } pthread_mutex_destroy(&pool->mutexPool); pthread_mutex_destroy(&pool->mutexBusy); pthread_cond_destroy(&pool->notEmpty); pthread_cond_destroy(&pool->notFull); free(pool); pool = NULL; return 0; } // 给线程池 添加任务 void threadPoolAdd(ThreadPool *pool, threadHand_t func, void *arg) { pthread_mutex_lock(&pool->mutexPool); // 当 队列满 且 不关闭线程池 while (pool->QNum == pool->QSize && !pool->shutdown) { // 阻塞生产者线程 -- 拒绝策略 pthread_cond_wait(&pool->notFull, &pool->mutexPool); } // 关闭线程池 if (pool->shutdown) { pthread_mutex_unlock(&pool->mutexPool); return; } // 添加任务 pool->taskQueue[pool->QRear].func = func; pool->taskQueue[pool->QRear].arg = arg; pool->QRear = (pool->QRear + 1) % pool->QSize; pool->QNum++; // 唤醒线程去执行任务 pthread_cond_signal(&pool->notEmpty); info_err("%d\n", __LINE__); pthread_mutex_unlock(&pool->mutexPool); } // 获取线程池中 工作的线程个数 int threadPoolBusyNum(ThreadPool *pool) { pthread_mutex_lock(&pool->mutexBusy); int busyNum = pool->busyThreadNum; pthread_mutex_unlock(&pool->mutexBusy); return busyNum; } // 获取线程池中 活着的线程个数 int threadPoolAliveNum(ThreadPool *pool) { pthread_mutex_lock(&pool->mutexPool); int aliveNum = pool->liveThreadNum; pthread_mutex_unlock(&pool->mutexPool); return aliveNum; } // 管理线程 void* manager(void *arg) { ThreadPool *pool = (ThreadPool *)arg; while (!pool->shutdown) { // 每隔 3s 检测一次 sleep(3); // 取出当前线程池中任务的数量 和 当前线程的数量 pthread_mutex_lock(&pool->mutexPool); int QNum = pool->QNum; // 线程池任务数量 int liveNum = pool->liveThreadNum; // 当前线程数量 pthread_mutex_unlock(&pool->mutexPool); // 取出当前忙线程的个数 pthread_mutex_lock(&pool->mutexBusy); int busyNum = pool->busyThreadNum; pthread_mutex_unlock(&pool->mutexBusy); // 添加线程 -- 任务的个数 > 存活的线程个数 && 存活的线程数 < 最大线程数 if (QNum > liveNum && liveNum < pool->MAXThreadNum) { pthread_mutex_lock(&pool->mutexPool); int cnt = 0; for (int i = 0; i < pool->MAXThreadNum && cnt < CHANGENUM && pool->liveThreadNum < pool->MAXThreadNum; i++) { if (pool->threadID[i] == 0) { pthread_create(&pool->threadID[i], NULL, work, pool); cnt++; pool->liveThreadNum++; } } pthread_mutex_unlock(&pool->mutexPool); } // 销毁线程 忙线程*2 < 存活的线程数 && 存活的线程 > 最小线程数 if (busyNum * 2 < liveNum && liveNum > pool->MINThreadNum) { pthread_mutex_lock(&pool->mutexPool); pool->exitThreadNum = CHANGENUM; pthread_mutex_unlock(&pool->mutexPool); // 让工作的线程自杀 for (int i = 0; i < CHANGENUM; i++) { pthread_cond_signal(&pool->notEmpty); } } } return NULL; } // 工作线程 void* work(void *arg) { ThreadPool *pool = (ThreadPool *)arg; while (1) { pthread_mutex_lock(&pool->mutexPool); // 当前的任务队列是否为空 while (pool->QNum == 0 && !pool->shutdown) { // 阻塞工作线程 pthread_cond_wait(&pool->notEmpty, &pool->mutexPool); // 判断是否需要 销毁线程 if (pool->exitThreadNum > 0) { pool->exitThreadNum--; // 醒来之后 是上锁状态 线程退出之前不能带锁退出 pthread_mutex_unlock(&pool->mutexPool); // 退出该工作线程 threadExit(pool); } } if (pool->shutdown) { pthread_mutex_unlock(&pool->mutexPool); // 退出该工作线程 threadExit(pool); } // 从队列中取出一个任务 Task task; task.func = pool->taskQueue[pool->QFront].func; task.arg = pool->taskQueue[pool->QFront].arg; // front++ pool->QFront = (pool->QFront + 1) % pool->QSize; pool->QNum--; // 取出一个 尝试唤醒生产者线程 pthread_cond_signal(&pool->notFull); // 解锁 pthread_mutex_unlock(&pool->mutexPool); pthread_mutex_lock(&pool->mutexBusy); pool->busyThreadNum++; pthread_mutex_unlock(&pool->mutexBusy); // 函数指针,执行函数 task.func(task.arg); free(task.arg); task.arg = NULL; pthread_mutex_lock(&pool->mutexBusy); pool->busyThreadNum--; pthread_mutex_unlock(&pool->mutexBusy); } return NULL; } // 线程退出函数 void threadExit(ThreadPool *pool) { pthread_t tid = pthread_self(); for (int i = 0; i < pool->MAXThreadNum; i++) { if (tid == pool->threadID[i]) { pool->threadID[i] = 0; printf("thread %ld exiting...\n", tid); break; } } pthread_exit(NULL); }
main.c
#include "threadpool.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> void taskFunc(void *arg) { char *str = (char *)arg; printf("tid:%ld %s\n", pthread_self(), str); usleep(100000); } int main() { // 1. 初始化线程池 ThreadPool *pool = threadPoolInit(3, 10, 50); // 2. 创建任务 -- 任务函数 、任务数据 for (int i = 0; i < 100; i++) { char buf[20] = {0}; sprintf(buf, "task %d", i); char *str = malloc(strlen(buf) + 1 ); strcpy(str, buf); threadPoolAdd(pool, taskFunc, str); } // 3. 等待任务结束 sleep(10); // 4. 销毁线程池 threadPoolDestroy(pool); return 0; }
三. 练习—实现目录拷贝
threadpool.h
#ifndef __THREADPOOL_H__ #define __THREADPOOL_H__ #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define info_err(format, ...) { \ printf(format, __VA_ARGS__); \ perror(""); \ } // 线程池头文件 // 任务队列结构体 // 线程处理函数 typedef void (*threadHand_t) (void *); // 事件队列结构体 typedef struct task { threadHand_t func; void *arg; } Task; // 线程池结构体 typedef struct threadpool { // 事件队列 Task *taskQueue; // 顺序队列 int QSize; // 队列的最大元素个数 int QNum; // 队列中的事件个数 int QFront; // 队头 int QRear; // 队尾 // 线程池信息 pthread_t managerID; // 管理者线程ID pthread_t *threadID; // 消费者线程ID int MAXThreadNum; // 最大线程数量 int MINThreadNum; // 最小线程数量 int busyThreadNum; // 工作的线程 int liveThreadNum; // 活着的线程 int exitThreadNum; // 需要销毁的线程数量 pthread_mutex_t mutexPool; // 整个线程池的线程锁 pthread_mutex_t mutexBusy; // 忙线程的线程锁 pthread_cond_t notFull; // 事件队列不满 pthread_cond_t notEmpty; // 事件队列非空 // 线程池状态 0 表示使用 1表示销毁 int shutdown; } ThreadPool; // 创建线程池 并初始化 ThreadPool* threadPoolInit(int min, int max, int size); // 销毁线程池 int threadPoolDestroy(ThreadPool *pool); // 给线程池 添加任务 void threadPoolAdd(ThreadPool *pool, threadHand_t func, void *arg); // 获取线程池中 工作的线程个数 int threadPoolBusyNum(ThreadPool *pool); // 获取线程池中 活着的线程个数 int threadPoolAliveNum(ThreadPool *pool); // 管理线程 void *manager(void *arg); // 工作线程 void* work(void *arg); // 线程退出函数 void threadExit(ThreadPool *pool); #endif
threadpool.c
#include "threadpool.h" const int CHANGENUM = 2; // 一次最多增加的消费者线程数量 // 创建线程池 并初始化 /* min: 最小线程数--核心线程数量 max: 最大线程数 size: 任务队列的最大元素个数 */ ThreadPool* threadPoolInit(int min, int max, int size) { // 定义一个线程池结构体指针 ThreadPool *threadPool = NULL; do { // 给线程池空间分配 threadPool = malloc(sizeof(ThreadPool)); if (threadPool == NULL) { perror("threadPool malloc fail"); break; } /* 线程池事件队列初始化 */ threadPool->taskQueue = malloc(sizeof(Task) * size); if (threadPool->taskQueue == NULL) { perror("taskQueue malloc fail"); break; } threadPool->QSize = size; // 队列的最大元素个数 threadPool->QNum = 0; // 队列中的事件个数 threadPool->QFront = threadPool->QRear = 0; // 对头、队尾 /* 线程池信息初始化 */ threadPool->MAXThreadNum = max; // 最大线程数量 threadPool->MINThreadNum = min; // 最小线程数量 // 消费者线程ID threadPool->threadID = malloc(sizeof(threadPool->threadID) * max); if (threadPool->threadID == NULL) { perror("threadID malloc fail"); break; } // 将消费者线程ID全部初始化为0 memset(threadPool->threadID, 0, sizeof(threadPool->threadID) * max); threadPool->liveThreadNum = min; // 活着的线程 threadPool->busyThreadNum = 0; // 工作的线程 threadPool->exitThreadNum = 0; // 需要销毁的线程数量 if (pthread_mutex_init(&threadPool->mutexPool, NULL) != 0 || pthread_mutex_init(&threadPool->mutexBusy, NULL) != 0 || pthread_cond_init(&threadPool->notFull, NULL) != 0 || pthread_cond_init(&threadPool->notEmpty, NULL) != 0) { printf("mutex or cond fail\n"); break; } /* 线程池状态 0 表示使用 1表示销毁 */ threadPool->shutdown = 0; // 创建一个管理者线程 管理者线程ID:threadPool->managerID pthread_create(&(threadPool->managerID), NULL, manager, threadPool); for (int i = 0; i < min; i++) { // 创建线程 线程池工作的最小线程 pthread_create(&(threadPool->threadID[i]), NULL, work, threadPool); } return threadPool; } while(0); if (threadPool && threadPool->threadID) { free(threadPool->threadID); } if (threadPool && threadPool->taskQueue) { free(threadPool->taskQueue); } if (threadPool) { free(threadPool); } return NULL; } // 销毁线程池 int threadPoolDestroy(ThreadPool *pool) { if (pool == NULL) { return -1; } // 关闭线程池 pool->shutdown = 1; // 阻塞回收管理者线程 pthread_join(pool->managerID, NULL); // 唤醒阻塞的消费者线程 for (int i = 0; i < pool->liveThreadNum; i++) { pthread_cond_signal(&pool->notEmpty); } // 释放堆内存 if (pool->taskQueue) { free(pool->taskQueue); } if (pool->threadID) { free(pool->threadID); } pthread_mutex_destroy(&pool->mutexPool); pthread_mutex_destroy(&pool->mutexBusy); pthread_cond_destroy(&pool->notEmpty); pthread_cond_destroy(&pool->notFull); free(pool); pool = NULL; return 0; } // 给线程池 添加任务 void threadPoolAdd(ThreadPool *pool, threadHand_t func, void *arg) { pthread_mutex_lock(&pool->mutexPool); // 当 队列满 且 不关闭线程池 while (pool->QNum == pool->QSize && !pool->shutdown) { // 阻塞生产者线程 -- 拒绝策略 pthread_cond_wait(&pool->notFull, &pool->mutexPool); } // 关闭线程池 if (pool->shutdown) { pthread_mutex_unlock(&pool->mutexPool); return; } // 添加任务 pool->taskQueue[pool->QRear].func = func; pool->taskQueue[pool->QRear].arg = arg; pool->QRear = (pool->QRear + 1) % pool->QSize; pool->QNum++; // 唤醒线程去执行任务 pthread_cond_signal(&pool->notEmpty); info_err("%d\n", __LINE__); pthread_mutex_unlock(&pool->mutexPool); } // 获取线程池中 工作的线程个数 int threadPoolBusyNum(ThreadPool *pool) { pthread_mutex_lock(&pool->mutexBusy); int busyNum = pool->busyThreadNum; pthread_mutex_unlock(&pool->mutexBusy); return busyNum; } // 获取线程池中 活着的线程个数 int threadPoolAliveNum(ThreadPool *pool) { pthread_mutex_lock(&pool->mutexPool); int aliveNum = pool->liveThreadNum; pthread_mutex_unlock(&pool->mutexPool); return aliveNum; } // 管理线程 void* manager(void *arg) { ThreadPool *pool = (ThreadPool *)arg; while (!pool->shutdown) { // 每隔 3s 检测一次 sleep(3); // 取出当前线程池中任务的数量 和 当前线程的数量 pthread_mutex_lock(&pool->mutexPool); int QNum = pool->QNum; // 线程池任务数量 int liveNum = pool->liveThreadNum; // 当前线程数量 pthread_mutex_unlock(&pool->mutexPool); // 取出当前忙线程的个数 pthread_mutex_lock(&pool->mutexBusy); int busyNum = pool->busyThreadNum; pthread_mutex_unlock(&pool->mutexBusy); // 添加线程 -- 任务的个数 > 存活的线程个数 && 存活的线程数 < 最大线程数 if (QNum > liveNum && liveNum < pool->MAXThreadNum) { pthread_mutex_lock(&pool->mutexPool); int cnt = 0; for (int i = 0; i < pool->MAXThreadNum && cnt < CHANGENUM && pool->liveThreadNum < pool->MAXThreadNum; i++) { if (pool->threadID[i] == 0) { pthread_create(&pool->threadID[i], NULL, work, pool); cnt++; pool->liveThreadNum++; } } pthread_mutex_unlock(&pool->mutexPool); } // 销毁线程 忙线程*2 < 存活的线程数 && 存活的线程 > 最小线程数 if (busyNum * 2 < liveNum && liveNum > pool->MINThreadNum) { pthread_mutex_lock(&pool->mutexPool); pool->exitThreadNum = CHANGENUM; pthread_mutex_unlock(&pool->mutexPool); // 让工作的线程自杀 for (int i = 0; i < CHANGENUM; i++) { pthread_cond_signal(&pool->notEmpty); } } } return NULL; } // 工作线程 void* work(void *arg) { ThreadPool *pool = (ThreadPool *)arg; while (1) { pthread_mutex_lock(&pool->mutexPool); // 当前的任务队列是否为空 while (pool->QNum == 0 && !pool->shutdown) { // 阻塞工作线程 pthread_cond_wait(&pool->notEmpty, &pool->mutexPool); // 判断是否需要 销毁线程 if (pool->exitThreadNum > 0) { pool->exitThreadNum--; // 醒来之后 是上锁状态 线程退出之前不能带锁退出 pthread_mutex_unlock(&pool->mutexPool); // 退出该工作线程 threadExit(pool); } } if (pool->shutdown) { pthread_mutex_unlock(&pool->mutexPool); // 退出该工作线程 threadExit(pool); } // 从队列中取出一个任务 Task task; task.func = pool->taskQueue[pool->QFront].func; task.arg = pool->taskQueue[pool->QFront].arg; // front++ pool->QFront = (pool->QFront + 1) % pool->QSize; pool->QNum--; // 取出一个 尝试唤醒生产者线程 pthread_cond_signal(&pool->notFull); // 解锁 pthread_mutex_unlock(&pool->mutexPool); pthread_mutex_lock(&pool->mutexBusy); pool->busyThreadNum++; pthread_mutex_unlock(&pool->mutexBusy); // 函数指针,执行函数 task.func(task.arg); free(task.arg); task.arg = NULL; pthread_mutex_lock(&pool->mutexBusy); pool->busyThreadNum--; pthread_mutex_unlock(&pool->mutexBusy); } return NULL; } // 线程退出函数 void threadExit(ThreadPool *pool) { pthread_t tid = pthread_self(); for (int i = 0; i < pool->MAXThreadNum; i++) { if (tid == pool->threadID[i]) { pool->threadID[i] = 0; printf("thread %ld exiting...\n", tid); break; } } pthread_exit(NULL); }
cp_dir.h
#ifndef __CP_DIR_H__ #define __CP_DIR_H__ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <dirent.h> #define MAXPATHNAMESIZE 512 // 拷贝文件 void taskFunc(void *arg); // 产生任务放入线程池 void cp_dir(ThreadPool *pool, char *dir_src, char *dir_dest); #endif
cp_dir.c
#include "cp_dir.h" #include "threadpool.h" // 拷贝文件 void taskFunc(void *arg) { char **pathname = (char **)arg; int fd1 = open(pathname[0], O_RDWR); if (fd1 == -1) { perror("open fd1 failed"); return; } int fd2 = open(pathname[1], O_RDWR | O_CREAT, 0777); if (fd2 == -1) { perror("open fd2 failed"); close(fd1); return; } // 不断的读取1.txt的内容,把读取到的内容写入到2.txt char buf[50] = {0}; while (1) { ssize_t r = read(fd1, buf, 50); if (0 == r) { // 读取完毕 break; } else if (-1 == r) { perror("read fd1 failed"); break; } ssize_t w = write(fd2, buf, r); if (-1 == w) { perror("write fd2 failed"); break; } } // 关闭两个文件 close(fd1); close(fd2); } // 产生任务放入线程池 void cp_dir(ThreadPool *pool, char *dir_src, char *dir_dest) { // 所有的路径都使用绝对路径 char abs_cur[MAXPATHNAMESIZE] = {0}; // 保存当前的工作路径 char abs_src[MAXPATHNAMESIZE] = {0}; // 源目录的绝对路径 char abs_dest[MAXPATHNAMESIZE] = {0}; // 目标目录的绝对路径 // 获取当前的工作路径 getcwd(abs_cur, MAXPATHNAMESIZE); // 获取源目录的绝对路径 chdir(dir_src); getcwd(abs_src, MAXPATHNAMESIZE); // 获取目标目录的绝对路径 chdir(abs_cur); // 切换到工作路径 mkdir(dir_dest, 0777); // 创建目标目录 chdir(dir_dest); getcwd(abs_dest, MAXPATHNAMESIZE); // 回到当前的工作路径 chdir(abs_cur); // 打开abs_src指定的目录 DIR *dirp = opendir(dir_src); // 读源目录的目录项 struct dirent *dp = NULL; while (dp = readdir(dirp)) { // 排除当前目录下的./.. if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) { continue; } char src_name[MAXPATHNAMESIZE] = {0}; sprintf(src_name, "%s/%s", abs_src, dp->d_name); char dest_name[MAXPATHNAMESIZE] = {0}; sprintf(dest_name, "%s/%s", abs_dest, dp->d_name); struct stat st; int ret = stat(src_name, &st); if (ret == -1) { perror("stat failed"); return; } if (S_ISDIR(st.st_mode)) { // 递归的查找子目录 cp_dir(pool, src_name, dest_name); } else if (S_ISREG(st.st_mode)) { char **pathname = malloc(sizeof(char*) * 2); // 传入线程函数的文件描述符 for (int i = 0; i < 2; i++) { pathname[i] = malloc(sizeof(char) * MAXPATHNAMESIZE); } strcpy(pathname[0], src_name); strcpy(pathname[1], dest_name); threadPoolAdd(pool, taskFunc, pathname); } } }
main.c
#include "threadpool.h" #include "cp_dir.h" int main(int argc, char *argv[]) { if (argc != 3) { printf("please input: ./a.out dir1 dir2\n"); return -1; } // 1. 初始化线程池 ThreadPool *pool = threadPoolInit(3, 10, 50); // 2. 创建任务 -- 任务函数 、任务数据 cp_dir(pool, argv[1], argv[2]); // 3. 等待任务结束 sleep(10); // 4. 销毁线程池 threadPoolDestroy(pool); return 0; }