您的位置:首页 > 运维架构 > Linux

linux C++ 面向对象线程类封装

2015-07-29 17:07 711 查看
转自 : 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函数。如下面这样的实现:

[cpp] view
plaincopy





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(测试文件):

[cpp] view
plaincopy





#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

[cpp] view
plaincopy





#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

[cpp] view
plaincopy





#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

[cpp] view
plaincopy





#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

[cpp] view
plaincopy





#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

[cpp] view
plaincopy





#include <iostream>

#include "thread.h"

using namespace std;

int main(int argv,char *argc)

{

MultiThread tt;

tt.start();

tt.join();

return 0;

}

运行结果







makefile参考

[plain] view
plaincopy





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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: