爲了實現高併發服務器,試驗了epoll+線程池的方式進行併發處理,效果並不理想。併發量主要受到線程池數目的約束,但是將線程池的實現記錄如下:
參考網上相關文章,實現了線程池,方便以後使用。
/*threadpool.h*/
#ifndef __THREADPOOL_H__
#define __THREADPOOL_H__
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>
#include<assert.h>
/*線程池會維護一個任務鏈表,每個thread_worker接頭結構就是一個任務*/
typedef struct worker{
/*回調函數,任務運行時會調用此函數*/
void (*process)(void *arg);
void *arg; /*回調參數*/
struct worker *next;
}thread_worker;
/*線程池結構*/
typedef struct
{
pthread_mutex_t queue_lock;
pthread_cond_t queue_ready;
/*鏈表結構*/
thread_worker *queue_head;
/*是否銷燬線程池*/
int tp_stop;
//線程數組
pthread_t *threadid;
/*線程池中允許的活動線程數目*/
int max_thread_num;
/*當前等待隊列的任務數目*/
int cur_queue_size;
}thread_pool;
//thread_pool *pool=NULL;
void pool_init(int max_thread_num);
/*向線程池的任務鏈表中加入一個任務*/
int pool_add_worker(void *(*process)(void *arg),void *arg);
int pool_destroy();
#endif
/*threadpool.c*/
#include "threadpool.h"
thread_pool *pool=NULL;
static void *thread_routine(void *arg);
void
pool_init(int max_thread_num){
pool=(thread_pool *)malloc(sizeof(thread_pool));
pthread_mutex_init(&(pool->queue_lock),NULL);
pthread_cond_init(&(pool->queue_ready),NULL);
pool->queue_head=NULL;
pool->max_thread_num=max_thread_num;
pool->cur_queue_size=0;
pool->tp_stop=0;
pool->threadid=(pthread_t *)malloc(max_thread_num *sizeof(pthread_t));
int i=0;
for(i=0;i<max_thread_num;i++){
pthread_create(&(pool->threadid[i]),NULL,thread_routine,NULL);
}
}
/*向線程池中加入任務*/
int pool_add_worker(void *(*process)(void *arg),void *arg){
/*構造一個新任務*/
thread_worker *newworker=
(thread_worker *)malloc(sizeof(thread_worker));
newworker->process=(void *)&process;
newworker->arg=arg;
newworker->next=NULL;
pthread_mutex_lock(&(pool->queue_lock));
/*將任務加入等待隊列中*/
thread_worker *member=pool->queue_head;
if(member!=NULL){
while(member->next!=NULL)
member=member->next;
member->next=newworker;
}else{
pool->queue_head=newworker;
}
assert(pool->queue_head!=NULL);
pool->cur_queue_size++;
pthread_mutex_unlock(&(pool->queue_lock));
/*此時等待隊列中有任務了,喚醒一個等待線程*/
pthread_cond_signal(&(pool->queue_ready));
return 0;
}
/*銷燬線程池,等待隊列中的任務不會再執行,
* 但是正在運行的線程會一直把任務運行完再退出*/
int pool_destroy(){
if(pool->tp_stop)
return -1;/*防止兩次調用*/
pool->tp_stop=1;
/*喚醒所有等待線程,線程池要銷燬了*/
pthread_cond_broadcast(&(pool->queue_ready));
/*阻塞等待線程退出,否則就成殭屍線程了*/
int i;
for(i=0;i<pool->max_thread_num;i++){
pthread_join(pool->threadid[i],NULL);
}
free(pool->threadid);
/*銷燬等待隊列*/
thread_worker *head=NULL;
while(pool->queue_head!=NULL){
head=pool->queue_head;
pool->queue_head=pool->queue_head->next;
free(head);
}
/*條件變量和互斥變量也需要銷燬*/
pthread_mutex_destroy(&(pool->queue_lock));
pthread_cond_destroy(&(pool->queue_ready));
free(pool);
pool=NULL;
return 0;
}
static void *
thread_routine(void *arg){
printf("starting thread 0x%x\n",pthread_self());
while(1){
pthread_mutex_lock(&(pool->queue_lock));
/*如果等待隊列爲0,並且不銷燬線程池,則處於阻塞狀態
* */
while(pool->cur_queue_size==0 && !pool->tp_stop){
printf("thread 0x%x is waiting\n",pthread_self());
pthread_cond_wait(&(pool->queue_ready),&(pool->queue_lock));
}
/*如果線程池要銷燬了*/
if(pool->tp_stop){
/*遇到break,continue,return等跳轉語句,千萬不要忘記先解鎖*/
pthread_mutex_unlock(&(pool->queue_lock));
printf("thread 0x%x will exit\n",pthread_self());
pthread_exit(NULL);
}
printf ("thread 0x%x is starting to work\n", pthread_self());
assert(pool->cur_queue_size!=0);
assert(pool->queue_head!=NULL);
/*等待隊列長度減去1,並卻出鏈表中的頭元素*/
pool->cur_queue_size--;
thread_worker *work=pool->queue_head;
pool->queue_head=work->next;
pthread_mutex_unlock(&(pool->queue_lock));
/*調用回調函數,執行任務*/
work->process(work->arg);
free(work);
work=NULL;
}
/*這一句話應該是不可達的*/
pthread_exit(NULL);
}
相關文章:
Linux--線程編程
http://www.cnblogs.com/forstudy/archive/2012/04/05/2433853.html