一个Linux下C线程池的实现

      在传统服务器结构中, 常是 有一个总的 监听线程监听有没有新的用户链接服务器, 每当有一个新的 用户进入, 服务器就开启一个新的线程用户处理这 个用户的数据包。这个线程只服务于这个用户 , 当 用户与服务器端关闭链接之后, 服务器端销毁这个线程。然而频繁地开辟与销毁线程极大地占用了系统的资源。并且在大量用户的状况下, 系统为了开辟和销毁线程将浪费大量的时间和资源。线程池提供了一个解决外部大量用户与服务器有限资源的矛盾, 线程池和传统的一个用户对应一个线程的处理方法不一样, 它的基本思想就是在程序 开始时就在内存中开辟一些线程, 线程的数目是 固定的,他们独自造成一个类, 屏蔽了对外的操做, 而服务器只须要将数据包交给线程池就能够了。当有新的客户请求到达时 , 不是新建立一个线程为其服务 , 而是从“池子”中选择一个空闲的线程为新的客户请求服务 ,服务完毕后 , 线程进入空闲线程池中。若是没有线程空闲 的 话, 就 将 数据 包 暂 时 积 累 , 等 待 线 程 池 内 有 线 程空闲之后再进行处理。经过对多个任务重用已经存在的线程对象 , 下降了对线程对象建立和销毁的开销。当客户请求 时 , 线程对象 已 经 存 在 , 可 以 提 高 请 求 的响应时间 , 从而总体地提升了系统服务的表现。
     通常来讲实现一个线程池主要包括如下几个组成部分:
1)线程管理器:用于建立并管理线程池。
2)工做线程:线程池中实际执行任务的线程。在初始化线程时会预先建立好固定数目的线程在池中,这些初始化的线程通常处于空闲状态,通常不占用CPU,占用较小的内存空间。
3)任务接口:每一个任务必须实现的接口,当线程池的任务队列中有可执行任务时,被空闲的工做线程调去执行(线程的闲与忙是经过互斥量实现的,跟前面文章中的设置标志位差很少),把任务抽象出来造成接口,能够作到线程池与具体的任务无关。
4)任务队列:用来存放没有处理的任务,提供一种缓冲机制,实现这种结构有好几种方法,经常使用的是队列,主要运用先进先出原理,另一种是链表之类的数据结构,能够动态的为它分配内存空间,应用中比较灵活,下文中就是用到的链表。
下面的不在赘述百度《线程池技术在并发服务器中的应用》写的很是详细! 服务器

      何时须要建立线程池呢?简单的说,若是一个应用须要频繁的建立和销毁线程,而任务执行的时间又很是短,这样线程建立和销毁的带来的开销就不容忽视,这时也是线程池该出场的机会了。若是线程建立和销毁时间相比任务执行时间能够忽略不计,则没有必要使用线程池了。 网络

 

大多数的网络服务器,包括Web服务器都具备一个特色,就是单位时间内必须处理数目巨大的链接请求,可是处理时间倒是比较短的。在传统的多线程服务器模型中是这样实现的:一旦有个请求到达,就建立一个新的线程,由该线程执行任务,任务执行完毕以后,线程就退出。这就是"即时建立,即时销毁"的策略。尽管与建立进程相比,建立线程的时间已经大大的缩短,可是若是提交给线程的任务是执行时间较短,并且执行次数很是频繁,那么服务器就将处于一个不停的建立线程和销毁线程的状态。这笔开销是不可忽略的,尤为是线程执行的时间很是很是短的状况。 数据结构

  线程池就是为了解决上述问题的,它的实现原理是这样的:在应用程序启动以后,就立刻建立必定数量的线程,放入空闲的队列中。这些线程都是处于阻塞状态,这些线程只占一点内存,不占用CPU。当任务到来后,线程池将选择一个空闲的线程,将任务传入此线程中运行。当全部的线程都处在处理任务的时候,线程池将自动建立必定的数量的新线程,用于处理更多的任务。执行任务完成以后线程并不退出,而是继续在线程池中等待下一次任务。当大部分线程处于阻塞状态时,线程池将自动销毁一部分的线程,回收系统资源。 多线程

  下面是一个简单线程池的实现,这个线程池的代码是我参考网上的一个例子实现的,因为找不到出处了,就没办法注明参考自哪里了。它的方案是这样的:程序启动以前,初始化线程池,启动线程池中的线程,因为尚未任务到来,线程池中的全部线程都处在阻塞状态,当一有任务到达就从线程池中取出一个空闲线程处理,若是全部的线程都处于工做状态,就添加到队列,进行排队。若是队列中的任务个数大于队列的所能容纳的最大数量,那就不能添加任务到队列中,只能等待队列不满才能添加任务到队列中。 并发

相关文章
相关标签/搜索