本来打算使用avl树套链表的结构,来避免优先级相等的情况,但是最后发现当绝大多数优先级都相等,avl树还是不可避免的退化成单链表,而需求中也确实是绝大多数都是优先级相等。
所以评估之后觉得avl树带来的提升远不及其提升的复杂度,所以放弃该方案,改为链表实现,现将此前实验的代码整理如下,
AVL树部分应该没有问题。重要步骤做了注释
.c文件如下
c
//
// Created by Administrator on 2025/2/10.
//
#ifdef __cplusplus
extern "C" {
#endif
#include "threadpool.h"
#include <malloc.h>
#include <pthread.h>
#include "string.h"
///---------------------------链表操作----------------
/**
* @brief 比较两个节点的数据
* @param 数据1
* @param 数据2
* @return 0-相等 -1-不相等
* */
int compare_node(Task_t target1,Task_t target2){
return (target1.func == target2.func)&&(strncmp(target1.task_name,target2.task_name,strlen(target2.task_name))==0)&&(target1.priority == target2.priority);
}
//在尾巴插入一个节点
int list_insert_r(AVLData * list_head,AVLData new_node){
if (list_head == NULL) return 0;
// if (new_node == NULL) return 0; //新建数据节点必须在之前分配好内存
AVLData * newnode = (AVLData *)malloc(sizeof(AVLData));
if(newnode == NULL){
return -1; //内存开辟失败
}
(*newnode)=new_node;
AVLData * p= list_head;
//设置新节点数据
newnode->next = NULL;
newnode->key=newnode->task.priority;
while (p->next){//第一个节点不存数据
p=p->next;
}
p->next = newnode;
return 0;
}
/**
* @brief 删除节点,对比任务名,任务优先级和任务函数指针,全部一样删除
* @param list_head 链表头
* @param del_node 要删除的节点
* @return 0-删除成功 -1-删除失败
* */
int list_node_del(AVLData * list_head,Task_t del_node){
AVLData * p = list_head;
while (p->next){//
if(compare_node(p->next->task,del_node)==0){ //如果相等
break;
}
p = p->next;
}
if(p->next == NULL )
return -1; //未找到
AVLData * q = p->next;
p->next = p->next->next;
free(q);
return 0;
}
/**
* @brief 遍历节点
* @param list_head 链表首元结点
* */
int list_traverse(AVLData * list_head){
AVLData * p = list_head;
p=p->next;
while (p){
printf("节点数据\n");
p=p->next;
}
return 0;
}
///---------------------------AVL树----------------
// 获取节点高度
int get_avltree_height(AVLNode *node) {
if (node == NULL) return 0;
return node->height;
}
// 新建节点
AVLNode* avltree_newNode(AVLData data) {
AVLNode* node = (AVLNode*) malloc(sizeof(AVLNode));
if(node == NULL){
_exit(-1);//申请内存失败
}
node->data = data;
node->left = NULL;
node->right = NULL;
node->height = 1; // 新节点初始高度设为1
return node;
}
// 右旋
AVLNode *rightRotate(AVLNode *y) {
AVLNode *x = y->left;
AVLNode *T2 = x->right;
x->right = y; //自身插入原来自己左孩子的右节点 完成右旋
y->left = T2; //冲突的右孩变左孩
y->height = 1 + (get_avltree_height(y->left) > get_avltree_height(y->right) ? get_avltree_height(y->left) : get_avltree_height(y->right));
x->height = 1 + (get_avltree_height(x->left) > get_avltree_height(x->right) ? get_avltree_height(x->left) : get_avltree_height(x->right));
return x;
}
// 左旋
AVLNode *leftRotate(AVLNode *x) {
AVLNode *y = x->right;
AVLNode *T2 = y->left;
y->left = x; //原来节点变成其右孩子的左孩子 完成左旋
x->right = T2; //冲突左孩变右孩
//重新计算高度 左右孩子中最高的+自身
x->height = 1 + (get_avltree_height(x->left) > get_avltree_height(x->right) ? get_avltree_height(x->left) : get_avltree_height(x->right));
y->height = 1 + (get_avltree_height(y->left) > get_avltree_height(y->right) ? get_avltree_height(y->left) : get_avltree_height(y->right));
return y;
}
// 获取平衡因子
int getBalanceFactor(AVLNode *N) {
if (N == NULL) return 0;
return get_avltree_height(N->left) - get_avltree_height(N->right);
}
// 插入节点
AVLNode* avltree_insert(AVLNode* node, AVLData data) {
if (node == NULL)
return avltree_newNode(data);
if (data.key < node->data.key) //小的靠左
node->left = avltree_insert(node->left, data);
else if (data.key > node->data.key)
node->right = avltree_insert(node->right, data);
else{//相同节点这个需要在进行处理,考虑在该节点处增加链表存储相同优先级的
list_insert_r(&node->data,data); //在当前节点的数据链表后插入
return node;
}
node->height = 1 + (get_avltree_height(node->left) > get_avltree_height(node->right) ? get_avltree_height(node->left) : get_avltree_height(node->right));
int balance = getBalanceFactor(node);
if (balance > 1 && data.key < node->left->data.key) // LL型 右旋
return rightRotate(node);
if (balance < -1 && data.key > node->right->data.key) // RR型 左旋
return leftRotate(node);
if (balance > 1 && data.key > node->left->data.key) { //LR型 左旋左孩子 然后右旋
node->left = leftRotate(node->left);
return rightRotate(node);
}
if (balance < -1 && data.key < node->right->data.key) { //RL型 右旋右孩子 然后左旋
node->right = rightRotate(node->right);
return leftRotate(node);
}
return node;
}
// 查找最小值节点
AVLNode * minValueNode(AVLNode* node) {
AVLNode* current = node;
while (current->left != NULL)
current = current->left;
return current;
}
// 删除节点
AVLNode* avltree_deleteNode(AVLNode* root, AVLData data) {
if (root == NULL)
return root;
if ( data.key < root->data.key )
root->left = avltree_deleteNode(root->left, data);
else if( data.key > root->data.key )
root->right = avltree_deleteNode(root->right, data);
else { //等于的情况
if((root->left == NULL) || (root->right == NULL)) { //如果是叶子节点
AVLNode *temp = root->left ? root->left : root->right;
if (temp == NULL) { //没有子树
temp = root;
root = NULL; //如果是叶子节点 直接删除 这一步在返回时会赋值给上一层的 root->left 或者 root->right
} else //有一个子树
*root = *temp; // 单边为空 复制非空子项的内容 然后将节点删除
free(temp);
} else { //两边都不为空 两个子树
AVLNode* temp = minValueNode(root->right);//找到后驱节点 右边最接近删除节点的值
root->data = temp->data; //只替换值 保留左右子树和高度信息
root->right = avltree_deleteNode(root->right, temp->data); //将后驱节点删除,此时后驱节点必然是只有一个子树或者没有子树,坍缩为之前两种情况
}
}
if (root == NULL)
return root;
root->height = 1 + (get_avltree_height(root->left) > get_avltree_height(root->right) ? get_avltree_height(root->left) : get_avltree_height(root->right));
int balance = getBalanceFactor(root);
if (balance > 1 && getBalanceFactor(root->left) >= 0) //LL
return rightRotate(root);
if (balance > 1 && getBalanceFactor(root->left) < 0) { //LR
root->left = leftRotate(root->left);
return rightRotate(root);
}
if (balance < -1 && getBalanceFactor(root->right) <= 0) //RR
return leftRotate(root);
if (balance < -1 && getBalanceFactor(root->right) > 0) {//RL
root->right = rightRotate(root->right);
return leftRotate(root);
}
return root;
}
// 中序遍历打印
void inorderTraversal(AVLNode *root) {
if(root != NULL) {
inorderTraversal(root->left);
printf("%d ", root->data.key);
inorderTraversal(root->right);
}
}
/// ------------------------------线程池操作------------------------------------
void* thread_worker(void *arg) {
Thread_pool_t *pool = (Thread_pool_t*)arg;
while (1) {
pthread_mutex_lock(&pool->lock);
// // 调整队列中的任务优先级
// adjust_priority(pool->task_queue, pool->queue_start, pool->queue_end, pool->queue_size);
//
// while (pool->queue_count == 0 && !pool->shutdown) {
// pthread_cond_wait(&pool->cond, &pool->lock);
// }
// if (pool->shutdown) {
// pthread_mutex_unlock(&pool->lock);
// pthread_exit(NULL);
// }
//
// task_t *task = pool->task_queue[pool->queue_start];
// if (task->exec_count > 0 && difftime(time(NULL), task->last_exec_time) >= task->interval) {
// pool->queue_start = (pool->queue_start + 1) % pool->queue_size;
// pool->queue_count--;
//
// task->func(task->arg); // 执行任务
// task->last_exec_time = time(NULL);
// if (--task->exec_count > 0) {
// insert_task_by_priority(pool->task_queue, task, &pool->queue_start, &pool->queue_end, &pool->queue_count, pool->queue_size);
// } else {
// free(task);
// }
// } else {
// pthread_mutex_unlock(&pool->lock);
// continue;
// }
pthread_mutex_unlock(&pool->lock);
}
return NULL;
}
Thread_pool_t* thread_pool_init(int num_workers, int queue_size) {
Thread_pool_t *pool = (Thread_pool_t *)malloc(sizeof(Thread_pool_t));
if (pool == NULL) return NULL;
pool->num_workers = num_workers;
pool->queue_size = queue_size;
pool->workers = (pthread_t *)malloc(num_workers * sizeof(pthread_t));
pool->task_queue = (Task_t**)malloc(queue_size * sizeof(Task_t*));
pool->queue_start = 0;
pool->queue_end = 0;
pool->queue_count = 0;
pool->shutdown = 0;
pthread_mutex_init(&pool->lock, NULL);
pthread_cond_init(&pool->cond, NULL);
for (int i = 0; i < num_workers; ++i) {
if (pthread_create(&pool->workers[i], NULL, thread_worker, pool) != 0) {
fprintf(stderr, "线程创建失败\n");
_exit(-1);
}
}
return pool;
}
void insert_task_by_priority(Task_t **queue, Task_t *task, int *queue_start, int *queue_end, int *queue_count, int queue_size) {
int pos = *queue_end;
while (pos != *queue_start) {
int prev_pos = (pos - 1 + queue_size) % queue_size;
if (queue[prev_pos]->priority <= task->priority) break;
queue[pos] = queue[prev_pos];
pos = prev_pos;
}
queue[pos] = task;
*queue_end = (*queue_end + 1) % queue_size;
(*queue_count)++;
}
/**
* @param pool 线程池
* @param func 任务
* @param arg 任务参数
* @param priority 任务优先级
* @param exec_count 任务循环次数
* @param interval 任务执行间隔时间
* */
int thread_pool_submit(Thread_pool_t *pool, task_func func, void *arg, int priority, int exec_count, int interval) {
if (pool->queue_count == pool->queue_size) return -1;
Task_t *task = (Task_t *)malloc(sizeof(Task_t));
task->func = func;
task->arg = arg;
task->priority = priority;
task->exec_count = exec_count;
task->last_exec_time = time(NULL) - interval - 1; // 确保首次可以被执行
task->interval = interval;
pthread_mutex_lock(&pool->lock);
insert_task_by_priority(pool->task_queue, task, &pool->queue_start, &pool->queue_end, &pool->queue_count, pool->queue_size);
pthread_cond_signal(&pool->cond);
pthread_mutex_unlock(&pool->lock);
return 0;
}
#ifdef __cplusplus
}
#endif
.h文件如下
c
//
// Created by Administrator on 2025/2/10.
//
#ifndef DEVP_THREADPOOL_H
#define DEVP_THREADPOOL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <time.h>
#include <pthread.h>
#include <unistd.h>
typedef void (*task_func)(void*);
typedef struct {
task_func func; // 任务函数
char task_name[128]; // 任务名称
void* arg; // 任务参数
int priority; // 任务优先级
int exec_count; // 执行次数
long int last_exec_time; // 上次执行时间
long int interval; // 执行间隔时间(ms)
}Task_t;
// 线程池结构体
typedef struct {
int num_workers; //工作线程数
pthread_t *workers;
Task_t **task_queue;
int queue_size; //最大任务数
int queue_start;
int queue_end;
int queue_count;
pthread_mutex_t lock;
pthread_cond_t cond;
int shutdown; //线程退出
}Thread_pool_t;
///------------------------------------AVL树相关------------------------------------------
typedef struct avldata{
Task_t task; //保留一个首元结点不放数据
struct avldata *next ; //这里做链表来存储 相同优先级的任务
int key; //这里是key作为AVL树来排序的依据,默认和task内部的优先级相同,当然也可以绑定其它的数值
}AVLData;
// 定义AVL树节点
typedef struct AVLNode {
AVLData data;
struct AVLNode *left;
struct AVLNode *right; //作为树时使用
// struct AVLNode *next; //作为链表时使用
int height;
}AVLNode;
#ifdef __cplusplus
}
#endif
#endif //DEVP_THREADPOOL_H