1. Nœud de tâche
typedef void (*cb_fun)(void *); //任务结构体 typedef struct task { void *argv; //任务函数的参数(任务执行结束前,要保证参数地址有效) cb_fun handler; //任务函数(返回值必须为0 非0值用作增加线程,和销毁线程池) struct task *next; //任务链指针 }zoey_task_t;
Handler est un pointeur de fonction, qui est la fonction de tâche réelle, argv est le paramètre de la fonction et next pointe vers la tâche suivante.
2. Task Queue
typedef struct task_queue { zoey_task_t *head; //队列头 zoey_task_t **tail; //队列尾 unsigned int maxtasknum; //最大任务限制 unsigned int curtasknum; //当前任务数 }zoey_task_queue_t;
Head est le pointeur de tête de la file d'attente des tâches, tail est le pointeur de queue de la file d'attente des tâches, maxtasknum est la limite du nombre maximum de tâches dans la file d'attente et curtasknum est le courant nombre de tâches dans la file d'attente.
3. Thread pool
typedef struct threadpool { pthread_mutex_t mutex; //互斥锁 pthread_cond_t cond; //条件锁 zoey_task_queue_t tasks;//任务队列 unsigned int threadnum; //线程数 unsigned int thread_stack_size; //线程堆栈大小 }zoey_threadpool_t;
mutex est un verrou mutex et cond est un verrou conditionnel. mutex et cond assurent conjointement l'exclusion mutuelle des tâches du pool de threads à recevoir ou à ajouter.
tasks pointe vers la file d'attente des tâches.
Threadnum est le nombre de threads dans le pool de threads
Thread_stack_size est la taille de la pile de threads
4. Configuration de démarrage
//配置参数 typedef struct threadpool_conf { unsigned int threadnum; //线程数 unsigned int thread_stack_size;//线程堆栈大小 unsigned int maxtasknum;//最大任务限制 }zoey_threadpool_conf_t;
La structure de configuration de démarrage est constituée de certains paramètres lors de l'initialisation du pool de threads.
5. Initialisez le pool de threads
Vérifiez d'abord si les paramètres sont légaux, puis initialisez mutex, cond, key (pthread_key_t). La clé est utilisée pour lire et écrire des variables globales de thread. Cette variable globale contrôle si le thread se termine.
Créez enfin le fil de discussion.
zoey_threadpool_t* zoey_threadpool_init(zoey_threadpool_conf_t *conf) { zoey_threadpool_t *pool = null; int error_flag_mutex = 0; int error_flag_cond = 0; pthread_attr_t attr; do{ if (z_conf_check(conf) == -1){ //检查参数是否合法 break; } pool = (zoey_threadpool_t *)malloc(sizeof(zoey_threadpool_t));//申请线程池句柄 if (pool == null){ break; } //初始化线程池基本参数 pool->threadnum = conf->threadnum; pool->thread_stack_size = conf->thread_stack_size; pool->tasks.maxtasknum = conf->maxtasknum; pool->tasks.curtasknum = 0; z_task_queue_init(&pool->tasks); if (z_thread_key_create() != 0){//创建一个pthread_key_t,用以访问线程全局变量。 free(pool); break; } if (z_thread_mutex_create(&pool->mutex) != 0){ //初始化互斥锁 z_thread_key_destroy(); free(pool); break; } if (z_thread_cond_create(&pool->cond) != 0){ //初始化条件锁 z_thread_key_destroy(); z_thread_mutex_destroy(&pool->mutex); free(pool); break; } if (z_threadpool_create(pool) != 0){ //创建线程池 z_thread_key_destroy(); z_thread_mutex_destroy(&pool->mutex); z_thread_cond_destroy(&pool->cond); free(pool); break; } return pool; }while(0); return null; }
6. Ajouter une tâche
Commencez par demander un nœud de tâche, ajoutez le nœud à la file d'attente des tâches après l'instanciation, ++ le numéro de file d'attente des tâches actuel et informez les autres processus des nouvelles tâches. L'ensemble du processus est verrouillé.
int zoey_threadpool_add_task(zoey_threadpool_t *pool, cb_fun handler, void* argv) { zoey_task_t *task = null; //申请一个任务节点并赋值 task = (zoey_task_t *)malloc(sizeof(zoey_task_t)); if (task == null){ return -1; } task->handler = handler; task->argv = argv; task->next = null; if (pthread_mutex_lock(&pool->mutex) != 0){ //加锁 free(task); return -1; } do{ if (pool->tasks.curtasknum >= pool->tasks.maxtasknum){//判断工作队列中的任务数是否达到限制 break; } //将任务节点尾插到任务队列 *(pool->tasks.tail) = task; pool->tasks.tail = &task->next; pool->tasks.curtasknum++; //通知阻塞的线程 if (pthread_cond_signal(&pool->cond) != 0){ break; } //解锁 pthread_mutex_unlock(&pool->mutex); return 0; }while(0); pthread_mutex_unlock(&pool->mutex); free(task); return -1; }
7. Détruire le pool de threads
Détruire le pool de threads consiste en fait à ajouter des tâches à la file d'attente des tâches, mais la tâche ajoutée est de laisser le thread se fermer. La fonction z_threadpool_exit_cb quittera le thread après avoir défini le verrou sur 0. Un verrou de 0 signifie que ce thread s'est terminé, puis quitte le thread suivant. Après avoir quitté le fil de discussion, toutes les ressources sont libérées.
void zoey_threadpool_destroy(zoey_threadpool_t *pool) { unsigned int n = 0; volatile unsigned int lock; //z_threadpool_exit_cb函数会使对应线程退出 for (; n < pool->threadnum; n++){ lock = 1; if (zoey_threadpool_add_task(pool, z_threadpool_exit_cb, &lock) != 0){ return; } while (lock){ usleep(1); } } z_thread_mutex_destroy(&pool->mutex); z_thread_cond_destroy(&pool->cond); z_thread_key_destroy(); free(pool); }
C'est très simple, il suffit de générer un autre fil et le nombre de fils++. Verrouillage.
int zoey_thread_add(zoey_threadpool_t *pool) { int ret = 0; if (pthread_mutex_lock(&pool->mutex) != 0){ return -1; } ret = z_thread_add(pool); pthread_mutex_unlock(&pool->mutex); return ret; }
Lorsque num=0, définissez le nombre de threads sur infini.
void zoey_set_max_tasknum(zoey_threadpool_t *pool,unsigned int num) { if (pthread_mutex_lock(&pool->mutex) != 0){ return -1; } z_change_maxtask_num(pool, num); //改变最大任务限制 pthread_mutex_unlock(&pool->mutex); }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!int main()
{
int array[10000] = {0};
int i = 0;
zoey_threadpool_conf_t conf = {5,0,5}; //实例化启动参数
zoey_threadpool_t *pool = zoey_threadpool_init(&conf);//初始化线程池
if (pool == null){
return 0;
}
for (; i < 10000; i++){
array[i] = i;
if (i == 80){
zoey_thread_add(pool); //增加线程
zoey_thread_add(pool);
}
if (i == 100){
zoey_set_max_tasknum(pool, 0); //改变最大任务数 0为不做上限
}
while(1){
if (zoey_threadpool_add_task(pool, testfun, &array[i]) == 0){
break;
}
printf("error in i = %d\n",i);
}
}
zoey_threadpool_destroy(pool);
while(1){
sleep(5);
}
return 0;
}