1. 程式人生 > >從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 publicvoid
 run() {
3 
        ...
4 
    } 
5 
};
6 
7 //開啟執行緒 8 MyThread thread =new  MyThread;
9 thread.start();

2.宣告一個類實現Runnable介面並實現run方法:

1 class MyRunnable implements  Runnable {
2
 publicvoid
 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(00, threadProc, this0&
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 return0
;
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 return0;
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 on 2007-08-30 10:18 螞蟻終結者 閱讀(4219) 評論(8)  編輯 收藏 引用 所屬分類: C++