一、线程池基本模型要了解带有优先级的线程池模型首先要了解线程池的基本模型。本文将在介绍线程池的同时融入执行带有优先级任务的处理思路。1. 双链表维护数据结构用宏定义的方式用头插法来插入节点。可以用于线程工作队列的创建以及任务队列的创建。// 链表宏定义头插法 #define LIST_INSERT(item, list) do {\ (item)-prev NULL;\ (item)-next (list);\ if ((list) ! NULL) (list)-prev (item);\ (list) (item);\ }while(0)同样用宏定义的方式从头部移除节点。注意线程队列和任务队列都是用双链表维护的。在调用时需要将任务从任务队列的头部摘下但是无需将线程从线程队列上摘下具体调用哪个线程有系统决定。// 链表宏定义移除节点 #define LIST_REMOVE(item, list) do {\ if ((item)-next ! NULL) (item)-next-prev (item)-prev;\ if ((item)-prev ! NULL) (item)-prev-next (item)-next;\ if ((item) (list)) (list) (item)-next;\ (item)-next NULL;\ (item)-prev NULL;\ }while(0)二、 结构体1. 任务结构体任务结构体要有执行函数以及执行函数要用到的 user_data以及用来维护自身数据结构的两个指针。在基础任务结构体的基础上用 int 类型的 priority 来表明任务优先级的高低。// 任务结构体 typedef struct nTask { void (*task_func)(struct nTask *); void *user_data; int priority; // 优先级 1-10数字越大优先级越高 struct nTask *prev; struct nTask *next; } Task;2. 线程结构体线程结构体中需要引入管理者为后续在创建线程队列的代码中给每个线程找到管理者。便于 API 的传参以及调用。// 工作线程结构体 struct nWorker { pthread_t threadid; int terminate; // 1: 下班 0: 工作 struct PriorityThreadPool *manager; struct nWorker *prev; struct nWorker *next; };3. 管理者结构体管理者结构体负责管理任务队列以及线程队列。所以需要线程队列的头指针。由于任务时带有优先级的不妨创建一个任务队列的数组。由于工作队列时贡献资源需要引入锁进行保护。最后需要一个 int 类型 shutdown 来决定线程是否进行工作。typedef struct PriorityThreadPool { struct nWorker *workers; // 工作线程链表 struct nTask *tasks[NUM_PRIORITY_LEVELS]; // 按优先级分类的任务队列 pthread_mutex_t mutex; pthread_cond_t cond; int num_workers; int paused; // 1: 暂停状态批处理模式 0: 运行状态 } PriorityThreadPool;三、 API 设置API 主要有三个分别是线程创建 API推送任务 API, 销毁线程 API1. 线程创建 APIint nPriorityThreadPoolCreate(PriorityThreadPool *pool, int numWorkers) { if (pool NULL) return -1; if (numWorkers 1) numWorkers 1; if (numWorkers MAX_WORKERS) numWorkers MAX_WORKERS; memset(pool, 0, sizeof(PriorityThreadPool)); pthread_cond_init(pool-cond, NULL); pthread_mutex_init(pool-mutex, NULL); pool-num_workers numWorkers; pool-paused 1; // 默认创建后处于暂停状态批处理模式 // 创建工作线程 for (int i 0; i numWorkers; i) { struct nWorker *worker (struct nWorker *)malloc(sizeof(struct nWorker)); if (worker NULL) { perror(malloc); return -2; } memset(worker, 0, sizeof(struct nWorker)); worker-manager pool; worker-terminate 0; // 将工作线程加入链表 LIST_INSERT(worker, pool-workers); // 创建线程 int ret pthread_create(worker-threadid, NULL, nThreadPoolCallback, worker); if (ret) { perror(pthread_create); /* 传入一级指针即可, pool 是指针; PriorityThreadPool 中的 works 也是指针 传入 PriorityThreadPool 类型的指针, 就是拿到了结构体中 works 的二级指针 */ LIST_REMOVE(worker, pool-workers); free(worker); return -3; } } printf([✓] 创建优先级线程池成功工作线程数: %d默认暂停状态\n, numWorkers); return 0; }线程创建 API 中每创建一个线程线程都会进入 nThreadPoolCallback 这个回调函数中。注意整个创建过程并不是阻塞在 pthread_create 这个接口中如果创建失败LIST_REOVE 这个宏定义正常进行(1) 回调函数所有线程会被阻塞在 pthread_cond_wait 这个接口中等待被触发调用在线程取出对应的任务之后一定要先解锁然后再让取到任务的线程去执行任务。这样不会影响线程争抢任务。void *nThreadPoolCallback(void *arg) { struct nWorker *worker (struct nWorker *)arg; while(1) { pthread_mutex_lock(worker-manager-mutex); // 防御性编程检查所有优先级队列是否都为空 int has_task 0; for (int i 0; i NUM_PRIORITY_LEVELS; i) { if (worker-manager-tasks[i] ! NULL) { has_task 1; break; } } // 如果没有任务或者线程池处于暂停状态等待被唤醒 while (!has_task || worker-manager-paused) { if (worker-terminate) break; pthread_cond_wait(worker-manager-cond, worker-manager-mutex); // 再检查一遍 has_task 0; for (int i 0; i NUM_PRIORITY_LEVELS; i) { if (worker-manager-tasks[i] ! NULL) { has_task 1; break; } } } if (worker-terminate) { pthread_mutex_unlock(worker-manager-mutex); break; } // ✅ 从最高优先级开始获取任务 // NUM_PRIORITY_LEVELS - 1 对应优先级 10 // 0 对应优先级 1 struct nTask *task NULL; for (int i NUM_PRIORITY_LEVELS - 1; i 0; i--) { if (worker-manager-tasks[i] ! NULL) { task worker-manager-tasks[i]; LIST_REMOVE(task, worker-manager-tasks[i]); break; } } pthread_mutex_unlock(worker-manager-mutex); // 执行任务 if (task ! NULL) { task-task_func(task); } } return NULL; }2. 推送任务 API通过宏定义 LIST_INSERT 将带有优先级的任务插入优先级任务队列然后铜鼓 pthread_cond_signal 唤醒一个线程让线程去执行任务// 推送任务 int nPriorityThreadPoolPushTask(PriorityThreadPool *pool, struct nTask *task) { if (pool NULL || task NULL) return -1; // 检查优先级范围 if (task-priority 1 || task-priority NUM_PRIORITY_LEVELS) { printf([✗] 错误优先级 %d 超出范围 [1, %d]\n, task-priority, NUM_PRIORITY_LEVELS); return -2; } pthread_mutex_lock(pool-mutex); // 根据优先级选择对应的队列优先级 1→索引 0优先级 10→索引 9 int queue_index task-priority - 1; LIST_INSERT(task, pool-tasks[queue_index]); // 如果线程池不在暂停状态唤醒一个等待的线程 if (!pool-paused) { pthread_cond_signal(pool-cond); } pthread_mutex_unlock(pool-mutex); return 0; }3. 销毁线程 API销毁线程 API 的实现相对简单用 terminate 标志所有线程下班pthread_cond_broadcast 接口唤醒所有线程pthread_join 接口等待所有线程结束然后线程销毁即可。如果任务队列还有任务也进行对应的清理操作即可。int nPriorityThreadPoolDestroy(PriorityThreadPool *pool) { if (pool NULL) return -1; struct nWorker *worker NULL; // 标记所有工作线程下班 pthread_mutex_lock(pool-mutex); for (worker pool-workers; worker ! NULL; worker worker-next) { worker-terminate 1; } pthread_mutex_unlock(pool-mutex); // 唤醒所有等待的线程 pthread_cond_broadcast(pool-cond); // 等待所有线程结束 for (worker pool-workers; worker ! NULL; worker worker-next) { pthread_join(worker-threadid, NULL); } // 清理工作线程链表 struct nWorker *curr pool-workers; while (curr ! NULL) { struct nWorker *next curr-next; free(curr); curr next; } // 清理所有任务队列中的任务 for (int i 0; i NUM_PRIORITY_LEVELS; i) { struct nTask *task pool-tasks[i]; while (task ! NULL) { struct nTask *next task-next; free(task); task next; } } // 销毁锁和条件变量 pthread_mutex_destroy(pool-mutex); pthread_cond_destroy(pool-cond); printf([✓] 销毁线程池成功\n); return 0; }4. 线程池控制 API为了达成优先级高的任务先执行的策略采用将先将所有任务初始化让所有任务先进入任务队列然后再从任务队列由高到低依次取任务进行执行。(1) 暂停线程池 API// 暂停线程池进入批处理模式 int nPriorityThreadPoolPause(PriorityThreadPool *pool) { if (pool NULL) return -1; pthread_mutex_lock(pool-mutex); pool-paused 1; printf([✓] 线程池已暂停批处理模式\n); pthread_mutex_unlock(pool-mutex); return 0; }(2) 恢复线程池 API// 恢复线程池开始执行任务 int nPriorityThreadPoolResume(PriorityThreadPool *pool) { if (pool NULL) return -1; pthread_mutex_lock(pool-mutex); pool-paused 0; printf([✓] 线程池已恢复开始执行任务\n); // 唤醒所有等待的线程 pthread_cond_broadcast(pool-cond); pthread_mutex_unlock(pool-mutex); return 0; }四、 调用案例#include priority_threadpool.h #include stdio.h #include stdlib.h #include string.h #include unistd.h #include time.h // 任务执行函数, 由 task 进行调用 void task_func(struct nTask *task) { int task_id *(int *)task-user_data; printf( [执行中] 任务 ID%d, 优先级%d, 线程ID%lu\n, task_id, task-priority, pthread_self()); // 模拟任务执行时间 sleep(1); printf( [完成] 任务 ID%d, 优先级%d ✓\n, task_id, task-priority); // 清理资源 free(task-user_data); free(task); } int main() { printf(\n); printf( 优先级线程池演示程序批处理模式\n); printf(\n\n); printf(【阶段1创建线程池】\n); // 创建线程池只有 3 个工作线程 PriorityThreadPool pool; int ret nPriorityThreadPoolCreate(pool, 3); if (ret) { printf(创建线程池失败\n); return -1; } printf(\n【阶段2收集任务批处理模式】\n); printf( 总任务数: 10\n); printf( 工作线程数: 3\n); printf( 优先级范围: 1-10 (数字越大优先级越高)\n\n); // 定义任务 // - 3 个优先级为 1 的任务 // - 1 个优先级为 2 的任务 // - 1 个优先级为 3 的任务 // - 1 个优先级为 4 的任务 // - 1 个优先级为 5 的任务 // - 1 个优先级为 6 的任务 // - 2 个优先级为 7 的任务 struct config { int task_id; int priority; } configs[] { {1, 1}, {2, 7}, // 高优先级 {3, 1}, {4, 2}, {5, 7}, // 高优先级 {6, 3}, {7, 5}, {8, 4}, {9, 6}, {10, 1}, }; int num_tasks sizeof(configs) / sizeof(configs[0]); printf(【推送任务顺序】\n); // 推送所有任务此时线程池处于暂停状态任务入队但线程不会执行 for (int i 0; i num_tasks; i) { struct nTask *task (struct nTask *)malloc(sizeof(struct nTask)); if (task NULL) { perror(malloc); return -1; } memset(task, 0, sizeof(struct nTask)); task-task_func task_func; task-user_data (int *)malloc(sizeof(int)); *(int *)task-user_data configs[i].task_id; task-priority configs[i].priority; printf( 推送 Task%d (优先级%d)\n, configs[i].task_id, configs[i].priority); ret nPriorityThreadPoolPushTask(pool, task); if (ret) { printf(推送任务失败\n); return -1; } } printf(\n【任务队列状态】\n); printf( 所有任务已入队线程池处于暂停状态\n); printf( 等待所有任务收集完成...\n); sleep(2); // 确保所有任务都进入队列 printf(\n【阶段3开始执行任务】\n); printf( 恢复线程池开始按优先级执行任务\n); nPriorityThreadPoolResume(pool); printf(\n【任务执行顺序分析】\n); printf( 预期执行顺序优先级从高到低同一优先级按FIFO\n); printf( 优先级 7: Task2, Task5\n); printf( 优先级 6: Task9\n); printf( 优先级 5: Task7\n); printf( 优先级 4: Task8\n); printf( 优先级 3: Task6\n); printf( 优先级 2: Task4\n); printf( 优先级 1: Task1, Task3, Task10\n\n); printf(【实际执行过程】\n); printf( (批处理模式所有任务先入队再按优先级执行)\n\n); // 等待所有任务执行完毕 sleep(15); // 10 个任务 × 1 秒 一些缓冲时间 printf(\n【销毁线程池】\n); nPriorityThreadPoolDestroy(pool); printf(\n\n); printf( 批处理模式演示结束\n); printf(\n); return 0; }五、总结本文将所有任务入队之后再进行调用。其实采用抢占式调度的性能最高关于这种模式的实现我们下篇文章再会本文内容来自https://github.com/0voice
带有优先级的线程池实现
一、线程池基本模型要了解带有优先级的线程池模型首先要了解线程池的基本模型。本文将在介绍线程池的同时融入执行带有优先级任务的处理思路。1. 双链表维护数据结构用宏定义的方式用头插法来插入节点。可以用于线程工作队列的创建以及任务队列的创建。// 链表宏定义头插法 #define LIST_INSERT(item, list) do {\ (item)-prev NULL;\ (item)-next (list);\ if ((list) ! NULL) (list)-prev (item);\ (list) (item);\ }while(0)同样用宏定义的方式从头部移除节点。注意线程队列和任务队列都是用双链表维护的。在调用时需要将任务从任务队列的头部摘下但是无需将线程从线程队列上摘下具体调用哪个线程有系统决定。// 链表宏定义移除节点 #define LIST_REMOVE(item, list) do {\ if ((item)-next ! NULL) (item)-next-prev (item)-prev;\ if ((item)-prev ! NULL) (item)-prev-next (item)-next;\ if ((item) (list)) (list) (item)-next;\ (item)-next NULL;\ (item)-prev NULL;\ }while(0)二、 结构体1. 任务结构体任务结构体要有执行函数以及执行函数要用到的 user_data以及用来维护自身数据结构的两个指针。在基础任务结构体的基础上用 int 类型的 priority 来表明任务优先级的高低。// 任务结构体 typedef struct nTask { void (*task_func)(struct nTask *); void *user_data; int priority; // 优先级 1-10数字越大优先级越高 struct nTask *prev; struct nTask *next; } Task;2. 线程结构体线程结构体中需要引入管理者为后续在创建线程队列的代码中给每个线程找到管理者。便于 API 的传参以及调用。// 工作线程结构体 struct nWorker { pthread_t threadid; int terminate; // 1: 下班 0: 工作 struct PriorityThreadPool *manager; struct nWorker *prev; struct nWorker *next; };3. 管理者结构体管理者结构体负责管理任务队列以及线程队列。所以需要线程队列的头指针。由于任务时带有优先级的不妨创建一个任务队列的数组。由于工作队列时贡献资源需要引入锁进行保护。最后需要一个 int 类型 shutdown 来决定线程是否进行工作。typedef struct PriorityThreadPool { struct nWorker *workers; // 工作线程链表 struct nTask *tasks[NUM_PRIORITY_LEVELS]; // 按优先级分类的任务队列 pthread_mutex_t mutex; pthread_cond_t cond; int num_workers; int paused; // 1: 暂停状态批处理模式 0: 运行状态 } PriorityThreadPool;三、 API 设置API 主要有三个分别是线程创建 API推送任务 API, 销毁线程 API1. 线程创建 APIint nPriorityThreadPoolCreate(PriorityThreadPool *pool, int numWorkers) { if (pool NULL) return -1; if (numWorkers 1) numWorkers 1; if (numWorkers MAX_WORKERS) numWorkers MAX_WORKERS; memset(pool, 0, sizeof(PriorityThreadPool)); pthread_cond_init(pool-cond, NULL); pthread_mutex_init(pool-mutex, NULL); pool-num_workers numWorkers; pool-paused 1; // 默认创建后处于暂停状态批处理模式 // 创建工作线程 for (int i 0; i numWorkers; i) { struct nWorker *worker (struct nWorker *)malloc(sizeof(struct nWorker)); if (worker NULL) { perror(malloc); return -2; } memset(worker, 0, sizeof(struct nWorker)); worker-manager pool; worker-terminate 0; // 将工作线程加入链表 LIST_INSERT(worker, pool-workers); // 创建线程 int ret pthread_create(worker-threadid, NULL, nThreadPoolCallback, worker); if (ret) { perror(pthread_create); /* 传入一级指针即可, pool 是指针; PriorityThreadPool 中的 works 也是指针 传入 PriorityThreadPool 类型的指针, 就是拿到了结构体中 works 的二级指针 */ LIST_REMOVE(worker, pool-workers); free(worker); return -3; } } printf([✓] 创建优先级线程池成功工作线程数: %d默认暂停状态\n, numWorkers); return 0; }线程创建 API 中每创建一个线程线程都会进入 nThreadPoolCallback 这个回调函数中。注意整个创建过程并不是阻塞在 pthread_create 这个接口中如果创建失败LIST_REOVE 这个宏定义正常进行(1) 回调函数所有线程会被阻塞在 pthread_cond_wait 这个接口中等待被触发调用在线程取出对应的任务之后一定要先解锁然后再让取到任务的线程去执行任务。这样不会影响线程争抢任务。void *nThreadPoolCallback(void *arg) { struct nWorker *worker (struct nWorker *)arg; while(1) { pthread_mutex_lock(worker-manager-mutex); // 防御性编程检查所有优先级队列是否都为空 int has_task 0; for (int i 0; i NUM_PRIORITY_LEVELS; i) { if (worker-manager-tasks[i] ! NULL) { has_task 1; break; } } // 如果没有任务或者线程池处于暂停状态等待被唤醒 while (!has_task || worker-manager-paused) { if (worker-terminate) break; pthread_cond_wait(worker-manager-cond, worker-manager-mutex); // 再检查一遍 has_task 0; for (int i 0; i NUM_PRIORITY_LEVELS; i) { if (worker-manager-tasks[i] ! NULL) { has_task 1; break; } } } if (worker-terminate) { pthread_mutex_unlock(worker-manager-mutex); break; } // ✅ 从最高优先级开始获取任务 // NUM_PRIORITY_LEVELS - 1 对应优先级 10 // 0 对应优先级 1 struct nTask *task NULL; for (int i NUM_PRIORITY_LEVELS - 1; i 0; i--) { if (worker-manager-tasks[i] ! NULL) { task worker-manager-tasks[i]; LIST_REMOVE(task, worker-manager-tasks[i]); break; } } pthread_mutex_unlock(worker-manager-mutex); // 执行任务 if (task ! NULL) { task-task_func(task); } } return NULL; }2. 推送任务 API通过宏定义 LIST_INSERT 将带有优先级的任务插入优先级任务队列然后铜鼓 pthread_cond_signal 唤醒一个线程让线程去执行任务// 推送任务 int nPriorityThreadPoolPushTask(PriorityThreadPool *pool, struct nTask *task) { if (pool NULL || task NULL) return -1; // 检查优先级范围 if (task-priority 1 || task-priority NUM_PRIORITY_LEVELS) { printf([✗] 错误优先级 %d 超出范围 [1, %d]\n, task-priority, NUM_PRIORITY_LEVELS); return -2; } pthread_mutex_lock(pool-mutex); // 根据优先级选择对应的队列优先级 1→索引 0优先级 10→索引 9 int queue_index task-priority - 1; LIST_INSERT(task, pool-tasks[queue_index]); // 如果线程池不在暂停状态唤醒一个等待的线程 if (!pool-paused) { pthread_cond_signal(pool-cond); } pthread_mutex_unlock(pool-mutex); return 0; }3. 销毁线程 API销毁线程 API 的实现相对简单用 terminate 标志所有线程下班pthread_cond_broadcast 接口唤醒所有线程pthread_join 接口等待所有线程结束然后线程销毁即可。如果任务队列还有任务也进行对应的清理操作即可。int nPriorityThreadPoolDestroy(PriorityThreadPool *pool) { if (pool NULL) return -1; struct nWorker *worker NULL; // 标记所有工作线程下班 pthread_mutex_lock(pool-mutex); for (worker pool-workers; worker ! NULL; worker worker-next) { worker-terminate 1; } pthread_mutex_unlock(pool-mutex); // 唤醒所有等待的线程 pthread_cond_broadcast(pool-cond); // 等待所有线程结束 for (worker pool-workers; worker ! NULL; worker worker-next) { pthread_join(worker-threadid, NULL); } // 清理工作线程链表 struct nWorker *curr pool-workers; while (curr ! NULL) { struct nWorker *next curr-next; free(curr); curr next; } // 清理所有任务队列中的任务 for (int i 0; i NUM_PRIORITY_LEVELS; i) { struct nTask *task pool-tasks[i]; while (task ! NULL) { struct nTask *next task-next; free(task); task next; } } // 销毁锁和条件变量 pthread_mutex_destroy(pool-mutex); pthread_cond_destroy(pool-cond); printf([✓] 销毁线程池成功\n); return 0; }4. 线程池控制 API为了达成优先级高的任务先执行的策略采用将先将所有任务初始化让所有任务先进入任务队列然后再从任务队列由高到低依次取任务进行执行。(1) 暂停线程池 API// 暂停线程池进入批处理模式 int nPriorityThreadPoolPause(PriorityThreadPool *pool) { if (pool NULL) return -1; pthread_mutex_lock(pool-mutex); pool-paused 1; printf([✓] 线程池已暂停批处理模式\n); pthread_mutex_unlock(pool-mutex); return 0; }(2) 恢复线程池 API// 恢复线程池开始执行任务 int nPriorityThreadPoolResume(PriorityThreadPool *pool) { if (pool NULL) return -1; pthread_mutex_lock(pool-mutex); pool-paused 0; printf([✓] 线程池已恢复开始执行任务\n); // 唤醒所有等待的线程 pthread_cond_broadcast(pool-cond); pthread_mutex_unlock(pool-mutex); return 0; }四、 调用案例#include priority_threadpool.h #include stdio.h #include stdlib.h #include string.h #include unistd.h #include time.h // 任务执行函数, 由 task 进行调用 void task_func(struct nTask *task) { int task_id *(int *)task-user_data; printf( [执行中] 任务 ID%d, 优先级%d, 线程ID%lu\n, task_id, task-priority, pthread_self()); // 模拟任务执行时间 sleep(1); printf( [完成] 任务 ID%d, 优先级%d ✓\n, task_id, task-priority); // 清理资源 free(task-user_data); free(task); } int main() { printf(\n); printf( 优先级线程池演示程序批处理模式\n); printf(\n\n); printf(【阶段1创建线程池】\n); // 创建线程池只有 3 个工作线程 PriorityThreadPool pool; int ret nPriorityThreadPoolCreate(pool, 3); if (ret) { printf(创建线程池失败\n); return -1; } printf(\n【阶段2收集任务批处理模式】\n); printf( 总任务数: 10\n); printf( 工作线程数: 3\n); printf( 优先级范围: 1-10 (数字越大优先级越高)\n\n); // 定义任务 // - 3 个优先级为 1 的任务 // - 1 个优先级为 2 的任务 // - 1 个优先级为 3 的任务 // - 1 个优先级为 4 的任务 // - 1 个优先级为 5 的任务 // - 1 个优先级为 6 的任务 // - 2 个优先级为 7 的任务 struct config { int task_id; int priority; } configs[] { {1, 1}, {2, 7}, // 高优先级 {3, 1}, {4, 2}, {5, 7}, // 高优先级 {6, 3}, {7, 5}, {8, 4}, {9, 6}, {10, 1}, }; int num_tasks sizeof(configs) / sizeof(configs[0]); printf(【推送任务顺序】\n); // 推送所有任务此时线程池处于暂停状态任务入队但线程不会执行 for (int i 0; i num_tasks; i) { struct nTask *task (struct nTask *)malloc(sizeof(struct nTask)); if (task NULL) { perror(malloc); return -1; } memset(task, 0, sizeof(struct nTask)); task-task_func task_func; task-user_data (int *)malloc(sizeof(int)); *(int *)task-user_data configs[i].task_id; task-priority configs[i].priority; printf( 推送 Task%d (优先级%d)\n, configs[i].task_id, configs[i].priority); ret nPriorityThreadPoolPushTask(pool, task); if (ret) { printf(推送任务失败\n); return -1; } } printf(\n【任务队列状态】\n); printf( 所有任务已入队线程池处于暂停状态\n); printf( 等待所有任务收集完成...\n); sleep(2); // 确保所有任务都进入队列 printf(\n【阶段3开始执行任务】\n); printf( 恢复线程池开始按优先级执行任务\n); nPriorityThreadPoolResume(pool); printf(\n【任务执行顺序分析】\n); printf( 预期执行顺序优先级从高到低同一优先级按FIFO\n); printf( 优先级 7: Task2, Task5\n); printf( 优先级 6: Task9\n); printf( 优先级 5: Task7\n); printf( 优先级 4: Task8\n); printf( 优先级 3: Task6\n); printf( 优先级 2: Task4\n); printf( 优先级 1: Task1, Task3, Task10\n\n); printf(【实际执行过程】\n); printf( (批处理模式所有任务先入队再按优先级执行)\n\n); // 等待所有任务执行完毕 sleep(15); // 10 个任务 × 1 秒 一些缓冲时间 printf(\n【销毁线程池】\n); nPriorityThreadPoolDestroy(pool); printf(\n\n); printf( 批处理模式演示结束\n); printf(\n); return 0; }五、总结本文将所有任务入队之后再进行调用。其实采用抢占式调度的性能最高关于这种模式的实现我们下篇文章再会本文内容来自https://github.com/0voice