周末看了nginx线程池部分的代码,顺手照抄了一遍,写成了自己的版本。实现上某些地方还是有差异的,不过基本结构全部摘抄。 在这里分享一下。如果你看懂了我的版本,也就证明你看懂了nginx的线程池。 本文只列出了关键数据结构和API,重在理解nginx线程池设计思路。完整代码在最后的链接里。 1.任务节点
handler为函数指针,是实际的任务函数,argv为该函数的参数,next指向下一个任务。 2.任务队列
head为任务队列头指针,tail为任务队列尾指针,maxtasknum为队列最大任务数限制,curtasknum为队列当前任务数。 3.线程池
mutex为互斥锁 cond为条件锁。mutex和cond共同保证线程池任务的互斥领取或者添加。 tasks指向任务队列。 threadnum为线程池的线程数 thread_stack_size为线程堆栈大小 4.启动配置
启动配置结构体是初始化线程池时的一些参数。 5.初始化线程池 首先检查参数是否合法,然后初始化mutex,cond,key(pthread_key_t)。key用来读写线程全局变量,此全局变量控制线程是否退出。 最后创建线程。
6.添加任务 首先申请一个任务节点,实例化后将节点加入任务队列,并将当前任务队列数++并通知其他进程有新任务。整个过程加锁。
7.销毁线程池 销毁线程池其实也是向任务队列添加任务,只不过添加的任务是让线程退出。z_threadpool_exit_cb函数会将lock置0后退出线程,lock为0表示此线程 已经退出,接着退出下一个线程。退出完线程释放所有资源。
8.增加一个线程 很简单,再生成一个线程以及线程数++即可。加锁。
9.改变任务队列最大任务限制 当num=0时设置线程数为无限大。
10.使用示例
11.源码 https://github.com/unlikewashface/zoey_threadpool.git 线程池可以发挥更多作用,比如可以把连接放到线程池里。nginx的异步加lua的协程是个非常好的组合,现在有了线程池后,线程池加协程将是另一个选择。总而言之,如果在保证性能的情况下,让nginx开发变得非常简单,这是非常利好的消息。 (责任编辑:IT) |