C++封装一个简单的线程类

多线程编程简介:

    大家在编程时,经常需要在程序中启动一个或多个线程来处理任务,而如果每次都是去调用系统创建线程的API函数来创建,代码量虽不多,但线程的创建和业务逻辑代码就揉在一起了,且创建多个线程的时候,有大量的重复代码,不便于维护。若我们把创建线程和销毁线程的这些共同的代码封装到一个类中,这样我们可以更专注业务逻辑的实现,在其它地方直接拿来用就行,程序也便于维护和扩展。而且这样的话即使程序所使用的线程库更换了,但线程类提供的接口没变,所以我们的业务逻辑代码也不用任何的改动。

    创建一个线程也无非就是调用系统线程API或第三方库的API,然后传入线程函数地址和线程运行所需要的参数即可,所以我们需要将此部分代码抽象出来,并提供使用接口即可。

 

一个线程基类Thread

    这里我们使用的是Apache提供的apr库,该库具有跨平台性,当然不管使用什么库,我们提供的接口都是一样的,且线程创建和销毁的逻辑是一样的。代码:

 1  class Thread
 2 {
 3  public:
 4     Thread( bool bDetach =  true);
 5      virtual ~Thread();
 6 
 7      virtual  void run() = 0;       // 业务接口
 8 
 9      int       start();               // 启动线程
10       int      join();                 // 等待线程线束
11       void    destroy();            // 销毁线程所申请的资源
12 
13       //  attribute functions
14       int      get_thread_id()        {  return thr_id_; }
15      void    set_thread_id(unsigned  long thrId) {    thr_id_ = thrId; }
16 
17  protected:
18      static     void* __stdcall thread_proc(apr_thread_t* th,  void* data);
19      void    notify() { cond_.signal(); }
20      bool    check_interrupt() {  return bExit_; }
21 
22  private:
23     size_t            thr_id_;         // 线程ID
24       bool            bExit_;             // 线程是否要退出标志
25 
26     apr_thread_t*    thr_;             // 线程句柄
27      Condition        cond_;             // 线程函数中等待任务的条件变量
28      
29  private:
30      // not implement
31      Thread( const Thread& );
32     Thread&  operator=( const Thread& );
33 };

一些说明:

  1. 我们在start()方法中调用apr库提供的线程API创建一个线程: apr_thread_create(),并将线程函数thread_proc()Thread*为线程函数参数传入apr_thread_create()即可,具体代码在后面贴出。
  2. Join()函数用于等待线束线程,而destroy()则是用于显示销毁该线程所占用的资源。
  3. 线程基类有一个纯虚函数run(),即应用线程继承Thread类后必须实现run()函数,即实现程序的业务逻辑
  4. start()创建完线程后系统便在某一时刻开始执行thread_proc()方法,我们在该方法中会调用run()函数,由于多态性,也就会调用应用程序多实现的run()函数了

具体实现(Thread.cpp):

 1  int    Thread::start()
 2 {
 3     apr_status_t        rv;
 4     apr_threadattr_t*    thrattr = NULL;    
 5     apr_threadattr_create(&thrattr, g_mpool);
 6 
 7      // 创建一个线程
 8       if ((rv = apr_thread_create(&thr_, thrattr, Thread::thread_proc,  this, g_mpool)) != APR_SUCCESS)
 9     {
10         set_error_code(rv);
11          char errbuf[512];
12         apr_strerror(rv, errbuf,  sizeof(errbuf));
13         log2DebugView("Thread: failed create a thread: [%d][%s]\n", rv, errbuf);
14          return rv;
15     }
16     apr_sleep(100000);         // ensure the thead_proc is running
17 
18      return rv;
19 }
20  // 等待线束线程
21  int    Thread::join()
22 {
23     bExit_    =  true;
24     notify();
25     apr_sleep(100000);
26 
27     apr_status_t rv = 0;
28      return apr_thread_join(&rv, thr_);
29 }
30  // 销毁线程
31  void Thread::destroy()
32 {
33      if (!bExit_)
34         join();
35     cond_.destroy();
36 }
37  // 线程函数,将会调用子类实现的run()方法
38  void* Thread::thread_proc(apr_thread_t* th,  void* data)
39 {
40     Thread* pthis = static_cast<Thread*>(data);
41      while (!pthis->bExit_)
42     {
43          // 调用子类实现的run()方法
44          pthis->run();
45 
46          // wait for signal
47          pthis->cond_.wait();
48     }
49 
50     printf("thread exit, id: %d\n", pthis->get_thread_id());
51     apr_thread_exit(th, APR_SUCCESS);
52      return NULL;
53 }

    这里我们不要太过意研究线程在具体代码是如何创建的,比如在start()函数中,在windows下线程函数可以是 UINT thread_proc(LPVOID param); 而创建线程则是调用__beginthreadex()的windows API即可,具体可参照windows的线程创建和销毁逻辑。线程使用如下:

应用示例

 1  // 继承Thread类并实现run()接口,有点类似Java或C#的用法
 2  class MyThread :  public Thread
 3 {
 4  public:
 5     MyThread(){ loop_ =  true; }
 6      virtual MyThread(){}
 7 
 8      // 只关心如何实现业务逻辑,而看不到线程是如何创建的
 9       virtual  void run()
10     {
11          while (loop)
12         {
13              // do some work
14          }
15         printf("MyThread exit.\n");
16     }
17 
18  private:
19      bool loop_;
20 };
21 
22  //  在程序中使用如下
23  MyThread* pmt =  new MyThread();
24 pmt->start();         // 调用start()方法后,即启动了一个线程了


    这样,我们就完成了一个线程类的封装和使用了,代码不多,但很常用哈。最后说明一下线程类中使用一个Condition的类,其实也就是一个对事件的封装使用,完全可以用windows下的 SetEvent()/WaitForSingleObject()替代或Linux下的pthread_condition_t的pthrad_condition_signal()/pthread_condition_wait()替代,即等待事件和通知事件的处理。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值