linux C++ 面向对象线程类封装
来源:互联网 发布:邦奇-威尔斯 知乎 编辑:程序博客网 时间:2024/06/05 11:47
转自 : http://blog.csdn.net/maotoula/article/details/18501963
1.封装遇到的问题
将pthread线程封装为抽象类,这样用户在使用线程时,只需要继承一下这个抽象类,并实现相应的接口就可以了。这样做的好处是用户可以将注意力集中在线程所要执行的逻辑上,而不需要关注创建线程、销毁线程等细节问题上。
我们抽象类的名称为Thread,其中有一个成员函数run,该函数为的声明形式为:
void run() = 0;
即将该成员函数声明为纯虚函数,用户继承此类必须要实现此成员函数。Thread中还有另外一个成员函数start,该函数的声明形式为:
void start();
用户在子类中调用start方法,将启动线程,并在线程中执行run函数。
最常想到的方法就是在start方法中使用pthread_create创建一个线程,并调用run函数。如下面这样的实现:
- 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,在此函数中在调用run函数,这样就顺利的迂回到了run函数。基于这种方法,我们可以用静态函数来封装一个简单的抽象类,以下为封装的代码,由三个文件构成:Thread.h(类的声明文件),Thread.cpp(类的实现文件),main.cpp(测试文件):
- #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
- #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++;
- }
- }
- }
- #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- #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
- #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
- #include <iostream>
- #include "thread.h"
- using namespace std;
- int main(int argv,char *argc)
- {
- MultiThread tt;
- tt.start();
- tt.join();
- return 0;
- }
运行结果
makefile参考
- 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
- linux C++ 面向对象线程类封装
- linux C++ 面向对象线程类封装
- linux C++ 面向对象线程类封装
- linux C++ 面向对象线程类(封装,继承,多态)
- linux开发:线程的面向对象封装
- 面向对象风格的线程类封装
- C用面向对象的方法封装矩阵类
- Object-c 面向对象之封装
- Objective-c语言_面向对象(封装)
- Objective-C语言_面向对象(封装)
- C开发经验1:面向对象封装
- Java面向对象--类、对象、封装
- Linux组件封装 使用面向对象编程封装Thread
- linux c面向对象分析
- 面向对象的线程池Threadpool的封装
- c++-面向对象类
- js面向对象 js类的封装
- JavaScript面向对象:分页器类封装
- HDOJ 1534 Schedule Problem 差分约束
- android 时间大小比较
- 块级元素与行内元素
- 文章标题
- iOS开发集成支付宝之:rsa_private read error : private key is NULL
- linux C++ 面向对象线程类封装
- c语言字符数组与字符串的使用详解
- 几种java通信(rmi,http,hessian,webservice)协议性能比较
- php验证码--图片
- LNMP环境搭建——MySQL篇
- Linux下的内核测试工具——perf使用简介
- POJ 1014 Dividing(二进制优化+多重背包)
- LeetCode222:Count Complete Tree Nodes
- HDOJ1272~小希的迷宫~并查集