本文共 2503 字,大约阅读时间需要 8 分钟。
看完《Windows核心编程》的“线程池”这一章后,仅仅是学到了几个Windows线程池相关的API的,并没有触及到线程池是如何实现的这个层次,总感觉意犹未尽,特别手痒,想要自己实现一个简单的线程池。偶然的,想起了之前买的祁宇老师的《深入应用C++11》中,有一章介绍“使用C++11实现一个线程池”,于是按照原书敲了一顿代码,在VS下顺利运行起来了,兴奋不已。然后,再深入一想,既然是纯C++实现的线程池,那么放到Linux下,也是可以运行的,于是又动手在Linux下折腾了一番,今日终于也运行起来了,特此记录,分享整个折腾过程。
一、线程池
本文主要介绍我在VS2015和Linux g++5.4.0下构建工程、编译和调试的过程,线程池的实现原理和代码解析,大家可以直接去看祁宇老师的书。但是,为免得突兀,我还是摘抄一部分原理如下:
一个完整的线程池包括三层:同步服务层、排队层和异步服务层,其实这也是一种生产者-消费者模式,同步层是生产者,不断将新任务丢到排队层中,因此,线程池需要提供一个添加新任务的接口供生产者使用;消费者是异步层,具体是有线程池中预先创建的线程去处理排队层中的任务。排队层是一个同步队列,它内部保证了上下两层对共享数据的安全访问,同时还要保证队列不会被无限制地添加任务导致内存暴涨。另外,线程池还要提供一个停止接口,让用户能够在需要的时候停止线程池的运行。
二、Windows平台运行
1,环境
1)硬件
通过cmd->systeminfo可以查看CPU信息
Intel64 Family 6Model 58 Stepping 9 GenuineIntel ~3201
它是一个四核处理器(通过process explorer -> system information,可以看到cores的数量)
2)软件
win10 X64 + VS2015
2,工程创建
1)使用VS2015新建一个win32 console工程,选择空项目,命名为Threadpool,其他默认即可。
2)从https://github.com/qicosmos/cosmos下载SyncQueue.hpp和ThreadPool.hpp,并添加进该工程。
3)添加一个main.cpp文件,用于测试。该文件由于没能在github上找到,我是照书抄的,并修改了书中的一处明显bug。如下:
#include "ThreadPool.hpp"int main(){ ThreadPool pool; std::thread thd1([&pool] { for (int i = 0; i < 10; ++i) { auto thdId = this_thread::get_id(); pool.AddTask([thdId] { cout << "syn layer1 thread ID : " << thdId << endl; }); } }); std::thread thd2([&pool] { for (int i = 0; i < 10; ++i) { auto thdId = this_thread::get_id(); pool.AddTask([thdId] { cout << "syn layer2 thread ID : " << thdId << endl; }); } }); this_thread::sleep_for(std::chrono::seconds(2)); //getchar(); cout << "clear thread pool..." << endl; pool.Stop(); thd1.join(); thd2.join(); cout << "main thread is over..." << endl; this_thread::sleep_for(std::chrono::seconds(5)); return 0;}
注:
1)书中在测试函数中,有这么两行代码:
ThreadPool pool; pool.start(2);事实上,start()函数是私有的,不可直接调用。另外,如果需要开指定次数的线程,直接在构造函数中传参即可,无须多次一举。
2)关于.hpp和.h的区别,可以参考博客http://blog.csdn.net/zhaojunshi886/article/details/5856175
简单来说,.hpp适合库文件,特别是模板库。
3)C++11的线程对象,以及线程对象的stop和join函数,和python的多线程库非常相似,看来C++有向更高级编程语言靠齐的趋势。
3,运行效果
三、Linux平台运行
1,环境
我是在VMware虚拟机上运行的ubuntu,环境参数如下图
2,构建工程
在Linux上构建c++工程就简单了,直接新建一个文件夹“Threadpool”,将上面的三个文件拷贝到该文件夹下即可
3,编译
1)直接输入“g++ -o Threadpool main.cpp”,报错
报了好几屏错误,看开头部分,应该是没有选择c++11支持。
2)添加c++11支持,“g++ -o Threadpool -std= c++11 main.cpp”,仍有错误
通过关键词“undefined reference to 'pthread_create'”去google搜索,可知:
pthread不是Linux下的默认的库,也就是在链接的时候,无法找到phread库中该函数的入口地址,于是链接会失败。
需要添加“-pthread”编译选项。注意,老版本是添加“-lpthread”,这里要感谢http://blog.chinaunix.net/uid-25909722-id-3026989.html,刚开始我一直添加“-lpthread”,并不能解决该编译错误
3)添加“-pthread”编译选项,编译成功,运行如下图: