1.封装遇到的问题
将pthread线程封装为抽象类,这样用户在使用线程时,只需要继承一下这个抽象类,并实现相应的接口就可以了。这样做的好处是用户可以将注意力集中在线程所要执行的逻辑上,而不需要关注创建线程、销毁线程等细节问题上。
我们抽象类的名称为Thread,其中有一个成员函数run,该函数为的声明形式为:
void run() = 0;
即将该成员函数声明为纯虚函数,用户继承此类必须要实现此成员函数。Thread中还有另外一个成员函数start,该函数的声明形式为:
void start();
用户在子类中调用start方法,将启动线程,并在线程中执行run函数。
最常想到的方法就是在start方法中使用pthread_create创建一个线程,并调用run函数。如下面这样的实现:
1 2 3 4 5 6 7 8 9 |
void start() { int status; status = pthread_create(_pThread,NULL,Thread::run,NULL); if(status != 0) err_abort(“creating thread failure”,status); } |
这样编译肯定是不能通过的,这是因为pthread_create要求的线程例程的接口形式为:
void *(*thread_routin)(void *args);
而上面代码中提供的线程例程的接口形式为:
void Thread::run()
显然不符合要求的接口。
为了能够在start中调用run函数,我们不得不采用一种迂回的方式。下面提供两种方法:一种是使用静态成员函数,另外一种是使用友元函数。
静态成员函数的作用域是全局的,而不仅仅局限于某个函数中。静态成员函数的实现方法和C语言中的普通函数类似,因此静态函数没有this指针,静态函数只能操作静态成员变量。之所以将静态函数封装到类中,在很大程度上也只是为了满足面向对象的特性之一—–封装性。
2.使用静态函数
需要特别注意的是mian函数中使用pthread_create的执行例程为MyThread类中的线程代理函数thread_proxy_func,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
#ifndef THREAD_H #define THREAD_H #include <iostream> #include <pthread.h> using namespace std; class Thread { private: //当前线程的线程ID pthread_t tid; //线程的状态 int threadStatus; //获取执行方法的指针 static void* run0(void* pVoid); static void * thread_proxy_func(void * args); //内部执行方法 void* run1(); public: //线程的状态-新建 static const int THREAD_STATUS_NEW = 0; //线程的状态-正在运行 static const int THREAD_STATUS_RUNNING = 1; //线程的状态-运行结束 static const int THREAD_STATUS_EXIT = -1; //构造函数 Thread(); //线程的运行实体 virtual void run()=0; //开始执行线程 bool start(); //获取线程ID pthread_t getThreadID(); //获取线程状态 int getState(); //等待线程直至退出 void join(); //等待线程退出或者超时 void join(unsigned long millisTime); }; class MultiThread : public Thread { public: void run() { int number = 0; for (int i = 0; i < 10; i++) { cout << "Current number is " << number++; cout << " PID is " << getpid() << " TID is " << getThreadID() << endl; sleep(1); } } }; #endif |
Thread.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
#include "thread.h" void* Thread::run0(void* pVoid) { Thread* p = (Thread*) pVoid; p->run1(); return p; } void* Thread::run1() { threadStatus = THREAD_STATUS_RUNNING; tid = pthread_self(); run(); threadStatus = THREAD_STATUS_EXIT; tid = 0; pthread_exit(NULL); } Thread::Thread() { tid = 0; threadStatus = THREAD_STATUS_NEW; } bool Thread::start() { int iRet = 0; pthread_create(&tid, NULL, thread_proxy_func, this) == 0; } pthread_t Thread::getThreadID() { return tid; } int Thread::getState() { return threadStatus; } void Thread::join() { if (tid > 0) { pthread_join(tid, NULL); } } void * Thread::thread_proxy_func(void * args) { Thread * pThread = static_cast<Thread *>(args); pThread->run(); return NULL; } void Thread::join(unsigned long millisTime) { if (tid == 0) { return; } if (millisTime == 0) { join(); }else { unsigned long k = 0; while (threadStatus != THREAD_STATUS_EXIT && k <= millisTime) { usleep(100); k++; } } } |
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include <iostream> #include <pthread.h> #include "thread.h" using namespace std; int main(int argv,char *argc) { MultiThread tt; tt.start(); tt.join(); return 0; } |
3.使用友元函数
友元函数的作用和静态函数相同,都起到一个代理的作用。需要将对象的指针作为参数传递给这个友元函数,然后在友元函数中调用run函数。代码如下,
由三个文件构成:Thread.h(类的声明文件),Thread.cpp(类的实现文件),main.cpp(测试文件):
Thread.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
#ifndef THREAD_H #define THREAD_H #include <iostream> #include <pthread.h> using namespace std; class Thread { private: //当前线程的线程ID pthread_t tid; //线程的状态 int threadStatus; //获取执行方法的指针 static void* run0(void* pVoid); //static void * thread_proxy_func(void * args); friend void * thread_proxy_func(void * args); //内部执行方法 void* run1(); public: //线程的状态-新建 static const int THREAD_STATUS_NEW = 0; //线程的状态-正在运行 static const int THREAD_STATUS_RUNNING = 1; //线程的状态-运行结束 static const int THREAD_STATUS_EXIT = -1; //构造函数 Thread(); //线程的运行实体 virtual void run()=0; //开始执行线程 bool start(); //获取线程ID pthread_t getThreadID(); //获取线程状态 int getState(); //等待线程直至退出 void join(); //等待线程退出或者超时 void join(unsigned long millisTime); }; class MultiThread : public Thread { public: void run() { int number = 0; for (int i = 0; i < 10; i++) { cout << "Current number is " << number++; cout << " PID is " << getpid() << " TID is " << getThreadID() << endl; sleep(1); } } }; #endif |
Thread.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
#include "thread.h" void* Thread::run0(void* pVoid) { Thread* p = (Thread*) pVoid; p->run1(); return p; } void* Thread::run1() { threadStatus = THREAD_STATUS_RUNNING; tid = pthread_self(); run(); threadStatus = THREAD_STATUS_EXIT; tid = 0; pthread_exit(NULL); } Thread::Thread() { tid = 0; threadStatus = THREAD_STATUS_NEW; } bool Thread::start() { int iRet = 0; pthread_create(&tid, NULL, thread_proxy_func, this) == 0; } pthread_t Thread::getThreadID() { return tid; } int Thread::getState() { return threadStatus; } void Thread::join() { if (tid > 0) { pthread_join(tid, NULL); } } void * thread_proxy_func(void * args) { Thread * pThread = static_cast<Thread *>(args); pThread->run(); return NULL; } void Thread::join(unsigned long millisTime) { if (tid == 0) { return; } if (millisTime == 0) { join(); }else { unsigned long k = 0; while (threadStatus != THREAD_STATUS_EXIT && k <= millisTime) { usleep(100); k++; } } } |
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 |
#include <iostream> #include "thread.h" using namespace std; int main(int argv,char *argc) { MultiThread tt; tt.start(); tt.join(); return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
ANAME=server CC=g++ TMP_PROGS = main.cpp thread.cpp PROGS = $(TMP_PROGS) OBJS = $(PROGS:.cpp=.o) INCDIR=./ all: $(ANAME) $(ANAME): $(OBJS) @echo "--------------- .o to ELT " $(CC) -g $(TMP_PROGS) -o $@ -lpthread .cpp.o: @echo "--------------- CPP to .o " $(CC) -g $(CFLAGS) -I$(INCDIR) -c $< -o $@ -lpthread clean: $(RM) $(ANAME) $(RM) *.o |
发表评论
要发表评论,您必须先登录。