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

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 * 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<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 <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 * 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::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


  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值