在Linux下写一个线程池以及线程池的一些用法和注意点

-->线程池介绍(大部分来自网络)

   在这个部分,详细的介绍一下线程池的作用以及它的技术背景以及他提供的一些服务等。大部分内容来自我日常生活中在网络中学习到的一些概念性的东西。

-->代码(大约240行)

   测试一下,具体的实现。

-->代码下载

--------------------------------------------------------------------------------------------------------------------------------------

-->线程池介绍

1、技术背景:服务器程序利用线程技术响应客户请求已经司空见惯,但是线程的使用是有待优化和处理的。单线程执行并不是一个高效的方式,这个时候可能就要考虑高并发,多线程等方式。线程池也是线程优化的一种方式。

在面向对象的过程中,对象的创建和销毁是非常占资源的,每创建一个对象都要获取内存资源以及其他一些资源。在Java中更是如此,他要跟踪每一个对象,在它使用完毕的时候,自动的销毁它并垃圾回收。可想而知,运行的速度之慢。这就产生了“池化技术”。

2、线程池如何提高服务器程序的性能?

●T1 = 创建线程

   ●T2 = 执行线程 包括访问共享数据、线程同步等

   ●T3 = 销毁线程

   ●T = T1 + T2 + T3

  单线程的情况下,系统花大量的时间再T1、T3阶段。我们要采取最优的措施,减少T1和T3的系统开销。线程池不仅调整T1,T3产生的时间段,而且它还显著减少了创建线程的数目。

假设:一台服务器,每天要处理10万个请求,这时候,我们比较不用线程池的技术和用线程池,他们的区别。
如果没有用线程池的话,那么程序将会用大把的时候来创建这10万个线程,用线程池,我们一般可用的线程数不会大于10万,所以可以大大减小开销。

3、具体工作流程

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。

4、何时不使用线程池线程  

● 如果需要使一个任务具有特定优先级

● 如果具有可能会长时间运行(并因此阻塞其他任务)的任务

● 如果需要将线程放置到单线程单元中(线程池中的线程均处于多线程单元中)

● 如果需要永久标识来标识和控制线程,比如想使用专用线程来终止该线程,将其挂起或按名称发现它

5、一般使用线程池的程序的特点

● 需要花费大量的时候,并且请求的时间比较短。

● 对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。

● 接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。

-->代码

     为了方便贴出代码,我全部放在一个文件里。运行gcc main.c -o main -lpthread -lrt运行

 #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <pthread.h> typedef struct condition
{
pthread_mutex_t pmutex;
pthread_cond_t pcond;
}condition_t; typedef struct task
{
void *(*run)(void *arg);
void *arg;
struct task *next;
}task_t; typedef struct threadpool
{
condition_t ready;
task_t *first;
task_t *last;
int counter;
int idle;
int max_threads;
int quit;
}threadpool_t; int condition_init(condition_t *cond)
{
int status;
if((status = pthread_mutex_init(&cond->pmutex,NULL)))//返回0代表初始化成功
return status;
if((status = pthread_cond_init(&cond->pcond,NULL)))
return status;
return ;
}
int condition_lock(condition_t *cond)
{
return pthread_mutex_lock(&cond -> pmutex);
}
int condition_unlock(condition_t *cond)
{
return pthread_mutex_unlock(&cond -> pmutex);
}
int condition_wait(condition_t *cond)
{
return pthread_cond_wait(&cond -> pcond,&cond -> pmutex);
}
int condition_timewait(condition_t *cond,const struct timespec *abstime)
{
return pthread_cond_timedwait(&cond->pcond,&cond->pmutex,abstime);
}
int condition_signal(condition_t *cond)
{
return pthread_cond_signal(&cond->pcond);
}
int condition_broadcast(condition_t *cond)
{
return pthread_cond_broadcast(&cond -> pcond);
}
int condition_destory(condition_t *cond)
{
int status;
if((status = pthread_mutex_destroy(&cond -> pmutex)))
return status;
if((status = pthread_cond_destroy(&cond -> pcond)))
return status;
return ;
} void *thread_routine(void *arg)
{
struct timespec abstime;
int timeout;
printf("thread 0x%0x is starting\n",(int)pthread_self());
threadpool_t *pool = (threadpool_t *)arg;
while()
{
timeout = ;
condition_lock(&pool -> ready);
pool -> idle++;
//等待队列有任务到来或者线程池销毁的通知
while(pool -> first == NULL && !pool -> quit)
{
printf("thread 0x%0x is waiting\n",(int)pthread_self());
clock_gettime(CLOCK_REALTIME,&abstime);
abstime.tv_sec += ;
int status=condition_timewait(&pool -> ready,&abstime);
if(status == ETIMEDOUT)
{
printf("thread 0x%0x is wait timed out\n",(int)pthread_self());
timeout = ;
break;
} }
//等到到条件,处于工作状态
pool -> idle--; if(pool -> first != NULL)
{
task_t *t = pool -> first;
pool -> first = t -> next;
//需要先解锁,以便添加新任务。其他消费者线程能够进入等待任务。
condition_unlock(&pool -> ready);
t -> run(t->arg);
free(t);
condition_lock(&pool -> ready);
}
//等待线程池销毁的通知
if(pool -> quit && pool ->first == NULL)
{
pool -> counter--;
if(pool->counter == )
{
condition_signal(&pool -> ready);
}
condition_unlock(&pool->ready);
//跳出循环之前要记得解锁
break;
} if(timeout &&pool -> first ==NULL)
{
pool -> counter--;
condition_unlock(&pool->ready);
//跳出循环之前要记得解锁
break;
}
condition_unlock(&pool -> ready);
} printf("thread 0x%0x is exiting\n",(int)pthread_self());
return NULL;
} //初始化
void threadpool_init(threadpool_t *pool, int threads)
{
condition_init(&pool -> ready);
pool -> first = NULL;
pool -> last = NULL;
pool -> counter = ;
pool -> idle = ;
pool -> max_threads = threads;
pool -> quit = ;
} //加任务
void threadpool_add_task(threadpool_t *pool, void *(*run)(void *arg),void *arg)
{
task_t *newstask = (task_t *)malloc(sizeof(task_t));
newstask->run = run;
newstask->arg = arg;
newstask -> next = NULL; condition_lock(&pool -> ready);
//将任务添加到对列中
if(pool -> first ==NULL)
{
pool -> first = newstask;
}
else
pool -> last -> next = newstask;
pool -> last = newstask;
//如果有等待线程,则唤醒其中一个
if(pool -> idle > )
{
condition_signal(&pool -> ready);
}
else if(pool -> counter < pool -> max_threads)
{
pthread_t tid;
pthread_create(&tid,NULL,thread_routine,pool);
pool -> counter++;
}
condition_unlock(&pool -> ready);
}
//销毁线程池
void threadpool_destory(threadpool_t *pool)
{ if(pool -> quit)
{
return;
}
condition_lock(&pool -> ready);
pool->quit = ;
if(pool -> counter > )
{
if(pool -> idle > )
condition_broadcast(&pool->ready); while(pool -> counter > )
{
condition_wait(&pool->ready);
}
}
condition_unlock(&pool->ready);
condition_destory(&pool -> ready);
} void *mytask(void *arg)
{
printf("thread 0x%0x is working on task %d\n",(int)pthread_self(),*(int*)arg);
sleep();
free(arg);
return NULL;
}
int main()
{
threadpool_t pool;
threadpool_init(&pool,); int i ;
for(i = ; i < ; i++)
{
int *arg = (int *)malloc(sizeof(int));
*arg = i;
threadpool_add_task(&pool,mytask,arg);
} sleep();//为了等待其他线程结束 当然也可以通过pthread_join来做
threadpool_destory(&pool);
return ;
}

-->代码下载

    Github

--------------------------------------------------------------------------------------------------------------------------------------

本文是我学习后,一些总结。比较基础,适合新接触Linux编程的人学习。请勿转载。

上一篇:一. Python基础(1)--语法


下一篇:安装mysql后遇到的一些问题