原文連結:http://blog.chinaunix.net/uid-26611383-id-4273854.html
文章開頭我想發幾句牢騷,也算是對過去幾個月的總結,有好幾個月沒有來更新部落格了,這期間發生了很多事情,換工作,接觸新的項目,這幾個月工作壓力有些大,現在算是完成了一個小項目的第一個階段,在這期間還是學到不少東西。對C++的理解增加了不少,以前很少用,雖然很喜歡,不過只是偏重於理論,C++確實博大精深,現在也只是懂了個皮毛。很高興我對C++,對Linux高度興趣,對現在的工作內容還是比較滿意的。從500強的外企義無反顧的離職,降薪來到一家創業公司還是值得的,我覺得人應該首先要知道自己想要什麼,自己喜歡什麼。這裡我想對還沒有畢業或者即將畢業的朋友們說,不要在乎公司的光環,別人覺得好的不一定適合你,不要在乎剛開始比同學少拿那幾百幾千塊錢,當你覺得整天上班只是一個工具,做著自己討厭的事情,那種感覺簡直生不如死。那些能讓你得到鍛煉並快速成長而且是你自己喜歡的工作才是真正適合你的工作,幾年之後你會發現那幾百幾千塊錢實在太微不足道。 這段時間看了不少C++代碼,也寫了一個小項目,這篇文章來說一下我見到過的比較通用的兩種多線程封裝方式,實現平台為Linux
首先說說地一種線程封裝方式,也是我們平常見得最多的一種封裝方式,是用物件導向中的繼承,多態來實現的,下面來看具體的代碼,這些代碼使我隨手寫的,主要是為了說明思想,如果要用到項目中還需要完善。
/************************************************************************* > File Name: Thread.cpp > Author: KevinFu > Mail: kevinfu1985@gmail.com > Created Time: 2014年05月26日 星期一 21時27分51秒 ************************************************************************/ #include<iostream> #include <pthread.h> using namespace std; class Thread { public: Thread(string name = "Unknown") { } virtual ~Thread() { } void Start() { pthread_create(&m_ThreadID, NULL, ThreadFunc, this); } static void* ThreadFunc(void* pth) { Thread* p = static_cast<Thread*>(pth); p->Run(); } virtual void Run() = 0; private: pthread_t m_ThreadID; }; class Test:public Thread { public: virtual void Run() { while(1) { cout<<"In Test::Run()"<<endl; } } }; int main() { Thread* thread1 = new Test(); thread1->Start(); sleep(1); }
這裡我們用Thread這個類來實現線程的封裝,使用者自己要啟用的線程類都要繼承這個Thread類,在Thread類的Start函數裡,調用了pthread_create建立了一個線程,並將ThreadFunc設定為線程函數,把線程的this指標傳遞給了這個函數,在這個線程函數裡調用了
虛函數Run,這個Run函數最終會利用多態調用到使用者線程類的Run函數,這就是上面代碼的基本原理,比較簡單,這也是物件導向用的比較多的地方,也可以說是他的強大的地方,不過用起來比較彆扭,我們公司的關於線程的封裝就是用的這種方法,個人感覺很麻煩,不好用,使用者要想啟用一個線程,必須要繼承Thread這個類,而且要覆蓋Run這個虛函數,很麻煩。
下面這種線程封裝方式是用基於對象的封裝方式,上面的封裝方式是物件導向的,這種方式我們用到了boost庫中的神器boost::function, boost::bind,這個神器原理就是幫定一個函數對象,函數對象可以包含參數,我們可以利用這個神器調用任意全域函數,甚至類的成員函數,
而不需要繼承自任何類,下面來看具體代碼
/************************************************************************* > File Name: Thread.cpp > Author: KevinFu > Mail: kevinfu1985@gmail.com > Created Time: 2014年05月26日 星期一 20時41分07秒 ************************************************************************/ #include<iostream> #include <pthread.h> #include <boost/function.hpp> #include <boost/bind.hpp> using namespace std; class Thread { typedef boost::function<void(void)> ThreadFunctionCallBack; public: Thread(ThreadFunctionCallBack cb, string name = "Unknow") :m_cb(cb) { } ~Thread() { } void Start(void) { pthread_create(&m_ThreadID, NULL, ThreadFunction, this); } static void* ThreadFunction(void* obj) { Thread* thread = static_cast<Thread*>(obj); thread->m_cb(); } private: ThreadFunctionCallBack m_cb; pthread_t m_ThreadID; }; class Test { public: void run(void) { cout<<"In test::run()"<<endl; } }; int main() { Test t; Thread thread1(boost::bind(&Test::run, &t)); thread1.Start(); usleep(100); }
我們可以看到Test類不需要繼承自Thread類,我們直接可以將boost::bind幫定的函數對象傳遞給Thread的建構函式,這裡為了簡單我們把this指標傳遞給了ThreadFunc,我們完全可以傳遞任何參數給ThreadFunc, 因為我們不需要使用多態,這就是基於對象的思想,比物件導向似乎更直接,使用起來更方便,更簡單。
C++11中的tr1中已經包含了boost這兩大功能,boost確實是代表著最高水平的C++庫,其中有很多東西值得學習,也有很多東西即將加入到標準C++庫中。