将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指针,静态函数只能操作静态成员变量。之所以将静态函数封装到类中,在很大程度上也只是为了满足面向对象的特性之一-----封装性。
需要特别注意的是mian函数中使用pthread_create的执行例程为MyThread类中的线程代理函数thread_proxy_func,在此函数中在调用run函数,这样就顺利的迂回到了run函数。基于这种方法,我们可以用静态函数来封装一个简单的抽象类,以下为封装的代码,由三个文件构成:Thread.h(类的声明文件),Thread.cpp(类的实现文件),main.cpp(测试文件):
#ifndef THREAD_H
#define THREAD_H
#include
#include
using namespace std;
class Thread
{
private:
//当前线程的线程ID
pthread_t tid;
//线程的状态
int threadStatus;
//获取执行方法的指针
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
#include "thread.h"
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(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
#include
#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
#include
using namespace std;
class Thread
{
private:
//当前线程的线程ID
pthread_t tid;
//线程的状态
int threadStatus;
//获取执行方法的指针
//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
#include "thread.h"
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(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
#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