zoukankan      html  css  js  c++  java
  • 线程池代码(通用版)

    一、适用场景

        首先,必须明确一点,线程池不是万能的,它有其特定的使用场景。使用线程池是为了减小线程本身的开销对应用性能所产生的影响,但是其 前提是线程本身创建、销毁的开销和线程执行任务的开销相比是不可忽略的 。如果线程本身创建、销毁的开销对应用程序的性能可以忽略不计,那么使用/不使用线程池对程序的性能并不会有太大的影响。

        线程池通常适合以下几种场景:

            ①、单位时间内处理的任务频繁,且任务时间较短

            ②、对实时性要求较高。如果接收到任务之后再创建线程,可能无法满足实时性的要求,此时必须使用线程池。

            ③、必须经常面对高突发性事件。比如Web服务器。如果有足球转播,则服务器将产生巨大冲击,此时使用传统方法,则必须不停的大量创建、销毁线程。此时采用动态线程池可以避免这种情况的发生。

    二、代码实现

    2.1 头文件

    #if !defined(__THREAD_POOL_H__)
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <memory.h>
    #include <pthread.h>
    #include <sys/types.h>
    
    // 布尔类型
    typedef int bool;
    #define false (0)
    #define true  (1)
    
    /* 线程任务链表 */
    typedef struct _thread_worker_t
    {
    	void *(*process)(void *arg);  /* 线程处理的任务 */
    	void *arg;                    /* 任务接口参数 */
    	struct _thread_worker_t *next;/* 下一个节点 */
    }thread_worker_t;
    
    /* 线程池对象 */
    typedef struct
    {
    	pthread_mutex_t queue_lock;   /* 队列互斥锁 */
    	pthread_cond_t queue_ready;   /* 队列条件锁 */
    
    	thread_worker_t *head;        /* 任务队列头指针 */
    	bool isdestroy;               /* 是否已销毁线程 */
    	pthread_t *threadid;          /* 线程ID数组 —动态分配空间 */
    	int num;                      /* 线程个数 */
    	int queue_size;               /* 工作队列当前大小 */
    }thread_pool_t;
    
    /* 函数声明 */
    extern int thread_pool_init(thread_pool_t **pool, int num);
    extern int thread_pool_add_worker(thread_pool_t *pool, void *(*process)(void *arg), void *arg);
    extern int thread_pool_destroy(thread_pool_t *pool);
    
    #endif /*__THREAD_POOL_H__*/
    

      

    2.2 函数实现

    /*************************************************************
     **功  能:线程池的初始化
     **参  数:
     **    pool:线程池对象
     **    num :线程池中线程个数
     **返回值:0:成功 !0: 失败
     *************************************************************/
    int thread_pool_init(thread_pool_t **pool, int num)
    {
    	int idx = 0;
    
            /* 为线程池分配空间 */
    	*pool = (thread_pool_t*)calloc(1, sizeof(thread_pool_t));
    	if(NULL == *pool)
    	{
    		return -1;
    	}
    
            /* 初始化线程池 */
    	pthread_mutex_init(&((*pool)->queue_lock), NULL);
    	pthread_cond_init(&((*pool)->queue_ready), NULL);
    	(*pool)->head = NULL;
    	(*pool)->num = num;
    	(*pool)->queue_size = 0;
    	(*pool)->isdestroy = false;
    	(*pool)->threadid = (pthread_t*)calloc(1, num*sizeof(pthread_t));
    	if(NULL == (*pool)->threadid)
    	{
    		free(*pool);
    		(*pool) = NULL;
    
    		return -1;
    	}
    
            /* 依次创建线程 */
    	for(idx=0; idx<num; idx++)
    	{
    		pthread_create(&((*pool)->threadid[idx]), NULL, thread_routine, *pool);
    	}
    
    	return 0;
    }
    

      

    /*************************************************************
     **功  能:将任务加入线程池处理队列
     **参  数:
     **    pool:线程池对象
     **    process:需处理的任务
     **    arg: process函数的参数
     **返回值:0:成功 !0: 失败
     *************************************************************/
    int thread_pool_add_worker(thread_pool_t *pool, void *(*process)(void *arg), void *arg)
    {
    	thread_worker_t *worker=NULL, *member=NULL;
    	
    	worker = (thread_worker_t*)calloc(1, sizeof(thread_worker_t));
    	if(NULL == worker)
    	{
    		return -1;
    	}
    
    	worker->process = process;
    	worker->arg = arg;
    	worker->next = NULL;
    
    	pthread_mutex_lock(&(pool->queue_lock));
    
    	member = pool->head;
    	if(NULL != member)
    	{
    		while(NULL != member->next) member = member->next;
    		member->next = worker;
    	}
    	else
    	{
    		pool->head = worker;
    	}
    
    	pool->queue_size++;
    
    	pthread_mutex_unlock(&(pool->queue_lock));
    	pthread_cond_signal(&(pool->queue_ready));
    
    	return 0;
    }
    

      

    /*************************************************************
     **功  能:线程池的销毁
     **参  数:
     **    pool:线程池对象
     **返回值:0:成功 !0: 失败
     *************************************************************/
    int thread_pool_destroy(thread_pool_t *pool)
    {
    	int idx = 0;
    	thread_worker_t *member = NULL;
    
    	if(false != pool->isdestroy)
    	{
    		return -1;
    	}
    
    	pool->isdestroy = true;
    
    	pthread_cond_broadcast(&(pool->queue_ready));
    	for(idx=0; idx<pool->num; idx++)
    	{
    		pthread_join(pool->threadid[idx], NULL);
    	}
    
    	free(pool->threadid);
    	pool->threadid = NULL;
    
    	while(NULL != pool->head)
    	{
    		member = pool->head;
    		pool->head = member->next;
    		free(member);
    	}
    
    	pthread_mutex_destroy(&(pool->queue_lock));
    	pthread_cond_destroy(&(pool->queue_ready));
    	free(pool);
    	
    	return 0;
    }
    

      

    /*************************************************************
     **功  能:线程池各个线程入口函数
     **参  数:
     **    arg:线程池对象
     **返回值:0:成功 !0: 失败
     *************************************************************/
    static void *thread_routine(void *arg)
    {
    	thread_worker_t *worker = NULL;
    	thread_pool_t *pool = (thread_pool_t*)arg;
    
    	while(1)
    	{
    		pthread_mutex_lock(&(pool->queue_lock));
    		while((false == pool->isdestroy) && (0 == pool->queue_size))
    		{
    			pthread_cond_wait(&(pool->queue_ready), &(pool->queue_lock));
    		}
    
    		if(false != pool->isdestroy)
    		{
    			pthread_mutex_unlock(&(pool->queue_lock));
    			pthread_exit(NULL);
    		}
    
    		pool->queue_size--;
    		worker = pool->head;
    		pool->head = worker->next;
    		pthread_mutex_unlock(&(pool->queue_lock));
    
                    /* 执行队列中的任务 */
    		(*(worker->process))(worker->arg);
    
    		free(worker);
    		worker = NULL;
    	}
    }
    

    学习版:https://www.cnblogs.com/cthon/p/9085026.html

    通用版代码:https://www.cnblogs.com/cthon/p/9097007.html  

    难度升级版代码:https://www.cnblogs.com/cthon/p/9085623.html

  • 相关阅读:
    偷窃转基因玉米种子引发中美打农业官司
    关于PreferenceActivity的使用和一些问题的解决(自己定义Title和取值)
    大写中文数字-財务
    【leetcode】LRU
    【AC大牛陈鸿的ACM总结贴】【ID AekdyCoin】人家当初也一样是菜鸟
    android面试题 不单单为了面试也是一次非常好的学习
    存储系统的实现-探析存储的机制和原理
    unity3d脚本编程
    ubuntu12.04 安装配置jdk1.7
    Android中一个类实现的接口数不能超过七个
  • 原文地址:https://www.cnblogs.com/cthon/p/9097007.html
Copyright © 2011-2022 走看看