本文共 2401 字,大约阅读时间需要 8 分钟。
看完《Windows核心编程》的“线程池”这一章后,我只学到了几个Windows线程池相关的API,并没有深入了解线程池的实现细节。尤其是每次编写多线程任务时都手动管理线程,确实让人觉得有点手痒。后来想起了祁宇老师的《深入应用C++11》,在书中找到了一章关于“使用C++11实现一个线程池”的内容,于是按照书中的代码在VS下编写了一个简单的线程池,成功运行后倍感兴奋。
接着,我又开始思考,如果将这个纯C++实现的线程池放到Linux下,是否也能运行呢?于是,在Linux环境下尝试了一番,今天终于实现了!以下是我在VS2015和Linux g++5.4.0下实现线程池的整个过程。
线程池的实现通常包括三层:同步服务层、排队层和异步服务层。这也是一种典型的生产者-消费者模式。具体来说:
线程池还需要提供一个停止接口,让用户能够在需要时停止线程池的运行。
cmd运行systeminfo可以查看CPU信息。我的开发机上配备了Intel64 Family 6 Model 58 Stepping 9 GenuineIntel,四核处理器(通过Process Explorer查看cores数量)。ThreadPool。SyncQueue.hpp和ThreadPool.hpp,并将这两个文件添加到项目中。main.cpp文件用于测试。由于没有找到合适的测试代码,我参考书中的内容并进行了修改。#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 << "同步层1 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 << "同步层2 thread ID : " << thdId << endl; }); } }); this_thread::sleep_for(std::chrono::seconds(2)); cout << "清空线程池..." << endl; pool.Stop(); thd1.join(); thd2.join(); cout << "主线程已过..." << endl; this_thread::sleep_for(std::chrono::seconds(5)); return 0;} 运行后,会看到两个线程分别执行任务,输出各自的线程ID。线程池在停止后,所有线程也会正确退出。
process explorer查看)ThreadPool,将SyncQueue.hpp、ThreadPool.hpp和main.cpp拷贝到该文件夹中。ls Threadpool可以确认文件是否存在。g++ -o Threadpool main.cpp,会报好几屏错误,提示没有选择C++11支持。-std=c++11后,仍然有错误,提示undefined reference to 'pthread_create'。通过搜索关键词undefined reference to 'pthread_create',我了解到在Linux下,pthread不是默认库,需要在编译时添加-pthread选项。具体来说,新版的gcc需要使用-pthread,而旧版本可能需要-lpthread。经过测试,发现新版本的gcc确实需要-pthread。
g++ -std=c++11 -pthread -o Threadpool main.cpp
运行./Threadpool后,会看到两个线程分别执行任务,输出各自的线程ID。线程池停止后,所有线程也会正确退出。
通过这次项目,我对线程池有了更深入的理解,特别是C++11在多线程编程中的优势。将同一段代码从Windows转到Linux,过程中遇到的pthread库问题让我对Linux开发有了更深的印象。未来,我计划进一步优化线程池的性能和功能,比如增加线程池的可扩展性和任务优先级的支持。
转载地址:http://mdqu.baihongyu.com/