前几天在学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 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();
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*/
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 *p = static_cast<Thread*> (param);
36 if (p->_target != 0 )
37 p->_target-> run();
38 else
39 p-> run();
40 return 0 ;
41 }
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 *p = 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 }
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接口还不够简洁,下一篇会有一个比较好的改进。
posted by 蚂蚁终结者