boost thread库作为boost库的一部分,为程序员使用跨平台的线程服务提供了便利的开发工具。

boost thread的基本概念与java的线程概念是一致的,使用的start-join方法。线程从创建成功即开始运行,join方法则同步等待线程结束。调用join方法的线程将会一直被阻塞直到启动的线程运行结束。

boost thread库与其他boost库一致,boost thread大量使用了c++模板技术。利用boost function和boost ref库为线程绑定运行函数。线程函数可以是全局函数或者类的静态成员函数,甚至可以是对象的成员函数。

boost thread 提供了三类线程管理对象。

  • thread类,基本的线程类。

  • threadgroup类,提供线程组管理,可以利用线程组做简单的线程池。

  • this_thread类,当前线程,它指的是程序运行时的线程对象。

下面以一个简单的过程为例,介绍如何使用boost thread库。

基本的线程使用方法:

    1. 利用全局函数作为线程函数


 
  
  1. void startThread1()  

  2. {  

  3.    boost::thread* calthread = new boost::thread(boost::bind(&calculate, 2000));  

  4.    outThreadId(calthread);  

  5.    calthread->join();  

  6. delete calthread;  

  7. }

    2. 利用静态成员函数作为线程函数


 
   
  1. void startThread2()  

  2. {  

  3.    boost::thread* calthread = new boost::thread(boost::bind(&calculator::scalculate, 3000));  

  4.    calthread->join();  

  5.    outThreadId(calthread);  

  6. delete calthread;  

  7. }

    3. 利用对象成员函数作为线程函数


 
   
  1. void startThread3()  

  2. {  

  3.    calculator calc;  

  4.    boost::thread* calthread = new boost::thread(boost::bind(&calculator::calculate, &calc, 4000));  

  5.    calthread->join();  

  6.    outThreadId(calthread);  

  7. delete calthread;  

  8. }

完整的代码示例:


 
  
  1. #ifdef WIN32  

  2. #include  

  3. #endif

  4. #include  

  5. #include

  6. /*  

  7. * 全局计算函数  

  8. */

  9. int calculate(int num)  

  10. {  

  11. return num;  

  12. }  

  13. class calculator  

  14. {  

  15. public:  

  16.    calculator();  

  17.    ~calculator();  

  18. public:  

  19. /*  

  20.     *  计算类的静态成员函数  

  21.    */

  22. staticint scalculate(int num);  

  23. /*  

  24.     *   计算类的普通成员函数  

  25.    */

  26. int calculate(int num);  

  27. private:  

  28. explicitconst calculator(const calculator&);  

  29. const calculator& operator=(const calculator&);  

  30. };  

  31. calculator::calculator()  

  32. {  

  33. }  

  34. calculator::~calculator()  

  35. {  

  36. }  

  37. int calculator::calculate(int num)  

  38. {  

  39.    ::calculate(num);  

  40. return 0;  

  41. }  

  42. int calculator::scalculate(int num)  

  43. {  

  44.    ::calculate(num);  

  45. return 0;  

  46. }  

  47. /*  

  48. *输出线程ID到屏幕  

  49. */

  50. void outThreadId(boost::thread* thd)  

  51. {  

  52. #ifdef WIN32  

  53.    assert(thd != NULL);  

  54. HANDLE handle = thd->native_handle();  

  55. DWORD tid = GetThreadId(handle);  

  56.    std::cout << "Thread id is: " << std::hex  << tid << std::endl;  

  57. #endif  

  58. }  

  59. /*  

  60. * 启动线程,以全局函数为线程函数  

  61. */

  62. void startThread1()  

  63. {  

  64.    boost::thread* calthread = new boost::thread(boost::bind(&calculate, 2000));  

  65.    outThreadId(calthread);  

  66.    calthread->join();  

  67. delete calthread;  

  68. }  

  69. /*  

  70. * 启动线程,以类的静态函数为线程函数  

  71. */

  72. void startThread2()  

  73. {  

  74.    boost::thread* calthread = new boost::thread(boost::bind(&calculator::scalculate, 3000));  

  75.    calthread->join();  

  76.    outThreadId(calthread);  

  77. delete calthread;  

  78. }  

  79. /*  

  80. * 启动线程,以对象成员函数为线程函数  

  81. * 注意:要保证对象在整个线程生命周期可以访问,否则将会发生不可预期错误。  

  82. */

  83. void startThread3()  

  84. {  

  85.    calculator calc;  

  86.    boost::thread* calthread = new boost::thread(boost::bind(&calculator::calculate, &calc, 4000));  

  87.    calthread->join();  

  88.    outThreadId(calthread);  

  89. delete calthread;  

  90. }  

  91. void usage()  

  92. {  

  93.    std::string usage = "usage: mytest.exe cmd, cmd is 1, 2,3";  

  94.    std::cout << usage << std::endl;  

  95. }  

  96. int main(int argc, char* argv[])  

  97. {  

  98. if(argc == 2)  

  99.    {  

  100. constchar cmd = argv[1][0];  

  101. switch(cmd)  

  102.        {  

  103. case'1':  

  104.            startThread1();  

  105. break;  

  106. case'2':  

  107.            startThread2();  

  108. break;  

  109. case'3':  

  110.            startThread3();  

  111. break;  

  112. default:  

  113.            usage();  

  114. break;  

  115.        }  

  116.    }  

  117. else

  118.    {  

  119.        usage();  

  120.    }  

  121. return 1;  

  122. }  


常见问题:

1. 如何获取线程ID?

   通过native_handler方法获取平台相关的句柄,然后通过平台API获取线程ID

   或者若在当前线程获取当前线程ID,直接使用平台API获取。

2. 如何知道线程有关状态?

   这同样是平台相关的,同样,首先取得平台相关的句柄,然后调用有关API进行操作。

3. 如何获取线程返回值?

    实际上这是一个线程同步问题,将在后续博文—boost thread使用--线程同步中详细说明。

4. 如何设定线程初始化和清理过程?

    初始化可以通过自己的函数实现,而清理函数则可以在初始化函数中注册清理函数实现。

    即可以利用boost::this_thread::at_exit_thread()方法实现


一些有用小技巧

1. 使用yield放弃时间片,从而别的线程将会获得执行的机会。

2. 使用interrupt可以使其它线程暂停执行,当boostthread库发出interrupt消息时,对应的线程对象将收到

  interrupted异常,从而可以暂停运行等

3. 利用hardware_concurrency可以获取系统的物理核心数


【参考资料】

  • boost 文档: http://www.boost.org/doc/libs/1_49_0/doc/html/thread/thread_management.html