线程池网络编程
多线程编程中,每有一个新连接时就会创建一个新的线程去维护连接进行收发数据,但是这会有一个问题,就是频繁的线程创造结束会使系统内核的负担加重,对于执行任务的效率也相对低下,因为还要多出创造线程的时间。





那么如何提高效率,减轻内核的负担呢?我们知道主要原因是由于频繁的创建线程。想要改善效率 不可能选择不创建线程。那只能让线程创建的时间提前,并且不会频繁的再结束再创建。因此就有了线程池的提出。
线程池就是一个进程在最开始先把工作 线程全部创建完毕,只有当需要用到某个线程的时候才工作。
不难想到要用阻塞的方式在每个线程的开始处堵住。在触发某些特定条件,例如主线程接受到新的连接时使一个堵塞住的函数线程变成运行状态去处理事件。并且这个函数线程应该是个死循环,即处理完某件事情后不应该结束,而是进入下一次循环 的堵塞状态,然后 等待之后的任务,这样就不会往复的创建新线程了。
因此大概的框架就是这样的。
函数线程
{
while(1)
{
阻塞;
工作;
}
}
主线程
{
创建n个函数线程。
while
{
接受任务
使一个阻塞条件开发,某个线程可以工作
}
}
因此具体使用的阻塞方式应该选择信号量比较合适。
例如 主线程初始化信号量为0,然后创建3个线程,每个线程里的while里开始为p操作,当主线程接受到链接后,进行一次v操作,然后3个线程中的某个线程就会竞争到一次p操作,然后执行,执行完毕后,进入下一次循环,堵在p操作上。
但上面最多同时处理三个链接,如果同时发起链接的客户端超过了3个,那么无论主线程怎么v,都无法使线程获取到那次的链接,因此要维护一个缓冲区的队列去存储链接描述符,假如缓冲区的多列大小有10个,那么同时就能接受13个链接,注意不是同时处理13个链接,而是处理3个链接,其余10个链接暂时存入缓冲区,如果前13个链接都没有处理完毕,第十四个链接来了那么只能丢弃了。因此可以把缓冲区设置大些。
用数组简单的模拟缓冲区队列,并用几个函数封装主要的操作。
主线程和函数线程
用一个客户端fork 20次去连接服务器 测试结果
结果
10秒后

其实进程池和线程池的思想也是一样,一开始fork很多子进程阻塞住,利用进程间的信号量控制机制。
然后父进程负责接受链接,v操作,不过这里值得注意的是,链接描述符c的传递,不像是线程的那样简单,线程由于都在一个进程中,共享一个pcb,描述符就是pcb里某个结构体数组的下标,所以描述符是啥就是啥。
但进程间就不一样,比如a进程的 描述符5 和 b进程的描述符5不是一个东西,虽然数字都是5,但是它们的pcb各不相同,5只表示pcb里某个成员数组的下标。因此需要特殊的传递方式,有兴趣可以参考《linux高性能服务器编程
》13.9的内容,在此不多重复。
》13.9的内容,在此不多重复。