线程池编程实验

实验目的

  1. 了解线程池的原理
  2. 了解线程池解决什么问题
  3. 掌握线程池的实现

实验内容

  1. 初始化线程池,在其中创建线程
  2. 执行完所有线程任务后,销毁线程池

实验原理

  • 在传统服务器结构中,常是有一个总的监听线程监听有没有新的用户连接服务器,每当有一个新的用户进入,服务器就开启一个新的线程用户处理这 个用户的数据包。这个线程只服务于这个用户,当用户与服务器端关闭连接以后,服务器端销毁这个线程。
  • 然而频繁地开辟与销毁线程极大地占用了系统的资源,而且在大量用户的情况下,系统为了开辟和销毁线程将浪费大量的时间和资源。线程池提供了一个解决外部大量用户与服务器有限资源的矛盾。
  • 线程池和传统的一个用户对应一个线程的处理方法不同,它的基本思想就是在程序开始时就在内存中开辟一些线程,线程的数目是固定的,他们独自形成一个类,屏蔽了对外的操作,而服务器只需要将数据包交给线程池就可以了。当有新的客户请求到达时,不是新创建一个线程为其服务,而是从“池子”中选择一个空闲的线程为新的客户请求服务,服务完毕后,线程进入空闲线程池中。如果没有线程空闲的话,就将数据包暂时积累, 等待线程池内有线程空闲以后再进行处理。通过对多个任务重用已经存在的线程对象,降低了对线程对象创建和销毁的开销。当客户请求 时,线程对象已经存在,可以提高请求的响应时间,从而整体地提高了系统服务的表现。

程序设计

#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include  <pthread.h>
#include  <unistd.h>
struct job
{
    void *(*func)(void *arg);
    void *arg;
    struct job *next;    
};

struct  threadpool
{
    int thread_num;//已开启的线程数量   
    pthread_t  *pthread_ids;//保存线程池中线程id

    struct job  *head;//任务队列的头指针
    struct job  *tail;//任务队列的尾指针
    int queue_max_num;//任务队列的最大数
    int queue_cur_num;//任务队列已有多少任务

    pthread_mutex_t  mutex;
    pthread_cond_t  queue_empty;//任务队列为空的条件
    pthread_cond_t  queue_not_empty;//任务队列不为空的条件
    pthread_cond_t  queue_not_full;//任务队列不为满的条件

};
//线程函数
void  *threadpool_function( void * arg)
{
    struct  threadpool  *pool =  (struct threadpool  *) arg  ;
    struct job *pjob = NULL;

    while(1)
    {
        pthread_mutex_lock( &(pool->mutex) );

        while(pool->queue_cur_num == 0)             //任务队列是否为空
        {
            pthread_cond_wait( &(pool->queue_not_empty), &(pool->mutex)  );
        }
        pjob = pool->head;
        pool->queue_cur_num --;

        if(pool->queue_cur_num != pool->queue_max_num)
        {
            pthread_cond_broadcast( &(pool->queue_not_empty) );
        }

        if ( pool->queue_cur_num==0 )
        {
            pool->head = pool->tail = NULL ;
            pthread_cond_broadcast( &(pool->queue_empty) );
        }
        else
        {
            pool->head = pool->head->next ;
        }

        pthread_mutex_unlock( &(pool->mutex) );

        (*(pjob->func))(pjob->arg);
        free(pjob);
        pjob = NULL ;
        
    }

}
//线程池初始化
struct threadpool *threadpool_init( int thread_num,int queue_max_num)
{
    struct threadpool  *pool=( struct threadpool * )malloc(  sizeof(struct threadpool)  );
    //malloc
    //int thread_num = 20;
    //int queue_max_num = 100;

    pool->thread_num = thread_num ;
    pool->queue_max_num = queue_max_num;
    pool->queue_cur_num = 0;
    pool ->head = NULL;
    pool->tail = NULL;

    pthread_mutex_init( &(pool->mutex) ,NULL );
    pthread_cond_init( &(pool->queue_empty), NULL );
    pthread_cond_init( &(pool->queue_not_empty) , NULL );
    pthread_cond_init( &(pool->queue_not_full) , NULL );

    pool->pthread_ids =  (pthread_t  *) malloc( sizeof(pthread_t) * thread_num );
    //malloc

    for ( int i = 0; i < pool->thread_num ; i++)
    {
        pthread_create( &(pool->pthread_ids[i ]) , NULL , threadpool_function , (void  *)pool );
    }

    return pool;
}
//添加任务函数
void threadpool_add_job(struct threadpool *pool,void *func(void *) , void * arg )
{
    pthread_mutex_lock(&(pool->mutex));
    while(pool->queue_cur_num == pool->queue_max_num)
    {
        pthread_cond_wait( &(pool->queue_not_full), &(pool->mutex) );
    }

    struct job  *pjob = (struct  job *)malloc ( sizeof(struct  job));
    //malloc
    pjob->func =  func ;
    pjob->arg = arg;

    if(NULL == pool->head)
    {
        pool->head = pool->tail =pjob;
        pthread_cond_broadcast(&(pool->queue_not_empty) );
    }
    else
    {
        pool->tail  ->next = pjob;
        pool->tail = pjob;
    }
    
    pool->queue_cur_num ++;

    pthread_mutex_unlock( &(pool->mutex) );
}

void * work ( void * arg )
{
    char * p =(char *)arg;
    printf("hello world   %s\n",p);
    printf("welcome to china   %s\n",p);
    sleep(1);
}
//资源回收
void   threadpool_destroy (struct threadpool *pool )
{
    pthread_mutex_lock(&(pool->mutex) );
    while( pool->queue_cur_num != 0 )
    {
        pthread_cond_wait( &(pool->queue_empty) , &(pool->mutex) );
    }
    pthread_mutex_unlock( &(pool->mutex) );
    pthread_cond_broadcast(&(pool->queue_empty) );
    pthread_cond_broadcast(&(pool->queue_not_empty) );
    pthread_cond_broadcast(&(pool->queue_not_full) );

    free(pool->pthread_ids);

    for( int i = 0 ; i< pool->thread_num ; i++)
    {
        pthread_cancel(pool->pthread_ids[i] );
        pthread_join(pool->pthread_ids[i] ,NULL );
    }
    struct job *temp;
    while(pool->head !=NULL )
    {
        temp = pool->head;
        pool->head = temp->next;
        free(temp);
    }
      free(pool);
    pthread_mutex_destroy(&(pool->mutex));       
    pthread_cond_destroy(&(pool->queue_empty));
    pthread_cond_destroy(&(pool->queue_not_empty));   
    pthread_cond_destroy(&(pool->queue_not_full));    
}
int main()
{
    struct  threadpool  * pool =  threadpool_init( 10,100 );    

    threadpool_add_job( pool , work , "1" ); 
    threadpool_add_job( pool , work , "2" ); 
    threadpool_add_job( pool , work , "3" ); 
    threadpool_add_job( pool , work , "4" ); 
    threadpool_add_job( pool , work , "5" ); 
    threadpool_add_job( pool , work , "6" ); 
    threadpool_add_job( pool , work , "7" ); 
    threadpool_add_job( pool , work , "8" ); 
    threadpool_add_job( pool , work , "9" ); 
    threadpool_add_job( pool , work , "10" ); 
    threadpool_add_job( pool , work , "11" ); 
    threadpool_add_job( pool , work , "22" ); 
    threadpool_add_job( pool , work , "33" ); 
    threadpool_add_job( pool , work , "44" ); 
    threadpool_add_job( pool , work , "55" ); 
    threadpool_add_job( pool , work , "66" ); 
    threadpool_add_job( pool , work , "77" ); 
    threadpool_add_job( pool , work , "88" ); 
    threadpool_add_job( pool , work , "99" ); 
    threadpool_add_job( pool , work , "100" ); 
    
    sleep(50);
    threadpool_destroy(pool );
   
    return 0;
}

运行结果

root@jsetc-virtual-machine:/0504# ./xcc
hello world   2
welcome to china   2
hello world   10
welcome to china   10
hello world   4
welcome to china   4
hello world   3
welcome to china   3
hello world   5
welcome to china   5
hello world   1
welcome to china   1
hello world   6
welcome to china   6
hello world   7
welcome to china   7
hello world   9
welcome to china   9
hello world   8
welcome to china   8
hello world   11
welcome to china   11
hello world   22
welcome to china   22
hello world   44
welcome to china   44
hello world   55
hello world   66
welcome to china   66
welcome to china   55
hello world   33
welcome to china   33
hello world   77
welcome to china   77
hello world   88
welcome to china   88
hello world   99
welcome to china   99
hello world   100
welcome to china   100
^C

实验总结

要是一个应用需要频繁的创建和销毁线程,任务执行的时间又比较短的话,就轮到线程池出场,但是线程创建和销毁的时间相比任务执行时间少很多的话,就没有必要用线程池了。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值