从Win32 API封装Thread类[1]

从Win32 API封装Thread类[1]

前几天在学Windows多线程程序设计,发现Win32 API用起来确实不怎么方便,特别是对于C++程序员。于是实现了一个简单的封装,技术含量当然不高,不过用起来还是比较方便的。如果你熟悉Java,你会发现这个实现有点像Java的Thread,在Java中有两种方法可以创建一个Thread:

1.从Thread类继承并实现run方法:

1  class  MyThread  extends  Thread {
2       public   void  run() {
3          ...
4      } 
5  };
6 
7  // 开启线程
8  MyThread thread  =   new  MyThread;
9  thread.start();

2.声明一个类实现Runnable接口并实现run方法:

1  class  MyRunnable  implements  Runnable {
2       public   void  run() {
3          ...
4      }
5  };
6 
7  //  开启线程 
8  MyThread thread  =   new  MyThread( new  MyRunnable);
9  thread.start();


具体实现
Java的实现方式还算优雅,我们也可以在C++中模拟,由于篇幅所限,在这里我们只关注基本功能的实现:
thread.h
 1  #ifndef THREAD_H
 2  #define THREAD_H
 3 
 4  #include  < windows.h >
 5 
 6  #define CLASS_UNCOPYABLE(classname) \
 7       private : \
 8      classname( const  classname & ); \
 9      classname &  operator = ( const  classname & );
10 
11  struct Runnable {
12      virtual  void  run()  =   0 ;
13      virtual  ~ Runnable() {}
14  };
15 
16  class  Thread :  public  Runnable {
17      CLASS_UNCOPYABLE(Thread)
18  public :
19      explicit Thread(Runnable * target  =   0 );
20      virtual  ~ Thread();
21      virtual  void  run() {}
22       void  start();
23       void  join();
24  private :
25       static  unsigned __stdcall threadProc( void * param);
26  private :
27      Runnable * _target;
28      HANDLE _handle;
29  };
30 
31  #endif /* THREAD_H */

在上面的代码中我们先定义一个Runnable类,并为Runnable类添加纯虚函数run,需要特别注意的是Runnable类的虚析构函数,任何想要成为基类的class都应该声明析构函数为virtual。
Thread类直接继承自Runnable,CLASS_UNCOPYABLE(Thread) 这一行用宏声明Thread类不可拷贝,具体细节请看 考虑用Macro替换Uncopyable 。start成员函数和Java中的一样,用来开启一个线程,join成员函数用来阻塞当前线程直到开启的线程执行完毕。threadProc作为静态成员函数用来传递给_beginthreadex,至于为什么用_beginthreadex代替CreateThread请问Google。初步的实现都比较简单,直接贴上代码:
thread.cpp
 1  #include  " thread.h "
 2  #include  < process.h >   // for _beginthreadex
 3 
 4  Thread::Thread(Runnable * target  /* = 0 */ )
 5  :_target( target )
 6  ,_handle( 0 ) {
 7 
 8  }
 9 
10  Thread:: ~ Thread() {
11       if  (_handle  !=   0 )
12          CloseHandle(_handle);
13       if  (_target  !=   0 )
14          delete _target;
15  }
16 
17  void  Thread::start() {
18       if  (_handle  !=   0 )
19           return ;
20      unsigned id;
21      _handle  =  reinterpret_cast < HANDLE > (
22          _beginthreadex( 0 0 , threadProc,  this 0 & id)
23          );
24  }
25 
26  void  Thread::join() {
27       if (_handle  !=   0 ) {
28          WaitForSingleObject(_handle, INFINITE);
29          CloseHandle(_handle);
30          _handle  =   0 ;
31      }
32  }
33 
34  unsigned __stdcall Thread::threadProc( void * param) {
35      Thread * =  static_cast < Thread *> (param);
36       if  (p -> _target  !=   0 )
37          p -> _target -> run();
38       else
39          p -> run();
40       return   0 ;
41  }

下面是测试代码:
test.cpp
 1  #include  " thread.h "
 2  #include  < iostream >
 3 
 4  using namespace std;
 5 
 6  // 第一种方法,从Thread类继承
 7  struct MyThread :  public  Thread {
 8      virtual  void  run() {
 9           for  ( int  i  =   0 ; i  <   5 ++ i) {
10              cout  <<   " MyThread Running... "   <<  i  <<  endl;
11              Sleep( 100 );
12          }
13      }
14  };
15 
16  // 第二种方法,“实现”Runnable接口
17  struct MyRunnable :  public  Runnable {
18      virtual  void  run() {
19           for  ( int  i  =   0 ; i  <   5 ++ i) {
20              cout  <<   " MyRunnable Running... "   <<  i  <<  endl;
21              Sleep( 300 );
22          }
23      }
24  };
25 
26  int  main() {
27 
28      MyThread thread1;
29      Thread thread2( new  MyRunnable());
30      thread1.start();
31      thread2.start();
32      thread1.join();
33      thread2.join();
34 
35       return   0 ;
36  }

可能的运行结果:
MyThread Running...0
MyRunnable Running...0
MyThread Running...1
MyThread Running...2
MyRunnable Running...1
MyThread Running...3
MyThread Running...4
MyRunnable Running...2
MyRunnable Running...3
MyRunnable Running...4


如果你熟悉boost库,你会知道boost库的Thread构造函数可以接受普通函数和函数对象作为参数,如果你觉得从Thread类继承或者实现Runnable接口还不够简洁,下一篇会有一个比较好的改进。

你可能感兴趣的:(从Win32 API封装Thread类[1])