1. 给用户添加任务的接口是 schedule(arg), arg应该如何设置
a) 创建 Work class, 将arg设置为 Work*, Work由用户创建,用户删除,线程池内仅保留对Work对象的引用
问题:我写完thread_pool后才发现,用户不再知道如何去删除他创建的 Work了,因为线程池内保存着指向Work的指针,线程池是自动析构的,因此,这种设计方法不可行
b) 设计方法和 a 一致,唯一的不同是线程池内复制了Work, 在类内,直接使用Work对象,不再使用指针了
问题:对于每一个局部变量都需要创建一个Work对象,假如用户数足够多的话,这是很耗时的。我写过的程序告诉我,尽量少的使用局部变量
c) 让用户创建 shared_ptr 类型的Work
问题:对于client来讲,太复杂了
最终方案:
schedule设置三个接口,一个接口符合Posix的线程调用习惯,直接使用 schedule(void(*func)(void*), (void*))。另一个接口使用 schedule(Work*), 最后一个接口schedule(Work)
线程池内部使用shared_ptr包含Work。
2. shutdown() 和shutdownNow()的设计
shutdown() 指示线程池不再接受新的任务
shutdownNow() 指示线程池唤醒所有的等待线程并对所有的线程执行 interrupt() 函数
3. 线程池析构函数的使用
线程池的析构函数和shutdown()类似,唤醒等待的线程(线程只有在工作队列为空的情况下才会去等待),并等待所有running的进程结束。析构函数不需要析构数据结构,因为数据结构都设置为 shared_ptr的。
4. 工作线程的启动方式
boost::thread 的启动函数只能在线程初始化时赋予,中途不得更改(没有这种接口),因此,线程池在初始化时让所有的工作线程进行无限循环等待任务,在循环体内接受shutdown() 或 shutdownNow() 任务