C/C++知识点之linux下线程的两种封装方式
小标 2018-08-10 来源 : 阅读 1820 评论 0

摘要:本文主要向大家介绍了C/C++知识点之linux下线程的两种封装方式,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

本文主要向大家介绍了C/C++知识点之linux下线程的两种封装方式,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

  
   在网络编程的时候往往需要对Linux下原生的pthread库中的函数进行封装,使其使用起来更加方便,封装方法一般有两种:面向对象和基于对象,下面将分别介绍这两种方式,最后统一分析这两种方式的优缺点:
面向对象:
面向对象的封装方式是通过虚函数提供回调功能,我们创建一个Thread类,然后设置一个run虚函数,使用时只需要重载这个类并实现其中的虚函数即可:
具体实现如下:

//------thread.h----------------

#ifndef _THREAD_H_
#define _THREAD_H_

#include 

class Thread
{
public:
    Thread();
    virtual ~Thread();
    void start();
    void join();
    void setAutoDelete(bool autoDelete);

private:
    static void* threadRoutine(void* args);
    virtual void run() = 0;
    pthread_t threadId_;
    bool autoDelete_;
};

#endif

详细实现如下:



//---------thread.c-------------------

#include "thread.h"
#include 
using namespace std;

Thread::Thread() : autoDelete_(false)
{
    cout << "Thread..." << endl;
}

Thread::~Thread()
{
    cout << "~Thread..." << endl;
}

void* Thread::threadRoutine(void* arg)
{
    Thread* thread = static_cast(arg);
    thread->run();

    if (thread->autoDelete_)
    {
        delete thread;
    }

    return NULL;
}


void Thread::start()
{
    pthread_create(&threadId_,NULL, threadRoutine,this);
}

void Thread::join()
{
    pthread_join(threadId_, NULL);
}

void Thread::setAutoDelete(bool autoDelete)
{
    autoDelete_ = autoDelete;
}

View Code

调用方式如下:


#include "thread.h"
#include 
#include 
using namespace std;

class TestThread : public Thread
{
public:
    TestThread(int count) : count_(count)
    {
        cout << "TestThread..." << endl;
    }
    ~TestThread()
    {
        cout << "~TestThread..." << endl;
    }
private:
    void run()
    {
        while( count_-- )
        {
            cout << "This is a test" << endl;
            sleep(1);
        }
    }

private:
    int count_;
};


int main(void)
{
    TestThread t(5);
    t.start();
    t.join();

    //do other work....
}

View Code
  可以看到,其中有一个私有的重虚函数run,使用时只需要继承thread,实现run函数,并在其内实现线程需要执行的逻辑就可以了。
  同时有一个静态的threadRoutine成员函数,因为C++成员函数缺省的调用方式是__thiscall,成员函数中隐含的第一个参数都是this指针,所以不能匹配给pthread_create的形参void *(*start_routine) (void *), 这时候就可以传递类的一个静态成员,把this指针做为该静态成员的参数。也就是start方法的: pthread_create(&threadId_,NULL, threadRoutine,this);   在threadRoutine函数中将接收到的void*类型的参数转换成Thread*就可以了,然后调用他的run方法。
  在main函数中静态创建了一个TestThread变量 t,然后启动线程, 但是如果线程运行结束了,这个变量 t 就失去存在的价值了, 总不能一直让它在哪里占用着栈上空间吧,此时我们就可以动态创建TestThread, 然后设定其autoDelete_属性,这样当该线程执行完毕后就会检查是否需要delete掉这个堆上变量,这就是autoDelete_属性的作用,可以将main函数修改如下:


int main(void)
{
    TestThread *t = new TestThread(5);
    t->setAutoDelete(true);
    t->start();
    t->join();

       //do other work....

}

View Code
  如果你决心只在堆上分配的话,就可以将析构函数设置为私有的,这样就可以只在堆上分配,但是你还得提供一个公有的自定义的析构方法。
基于对象
  基于对象的封装方法,实现思路同上,但是它不是通过虚函数的方式实现回调的功能,而是通过函数绑定的方式, boost库中的bind/function可以实现将一个函数转换成另一种函数,就算是成员函数也可以,它相当于C++中的bind1st,bin2nd等函数适配器,在C++11中也实现了bind/function, 关于boost bind/function的使用方法,可以看这里。这里不做过多介绍。
用基于对象的封装方法如下:

//-------thread.h-------

#ifndef _THREAD_H_
#define _THREAD_H_

#include 
#include 

class Thread
{
public:
    typedef boost::function ThreadFunc;
    explicit Thread(const ThreadFunc& func);
    ~Thread();
    void start();
    void join();
    void setAutoDelete(bool autoDelete);

private:
    static void* threadRoutine(void* args);
    void run();
    bool autoDelete_;
    ThreadFunc func_;
    pthread_t threadId_;

};

#endif

其中在构造函数中需要ThreadFunc对象,这个函数就是在run中调用的实例,可以看下面代码:


//---------thread.cpp-----------

#include "thread.h"
#include 
using namespace std;


Thread::Thread(const ThreadFunc& func):autoDelete_(false),func_(func)
{
    cout << "Thread..." << endl;
}


Thread::~Thread()
{
    cout << "~Thread..." << endl;
}


void Thread::run()
{
    func_();
}

void* Thread::threadRoutine(void* arg)
{
    Thread* thread = static_cast(arg);
    thread->run();

    if (thread->autoDelete_)
    {
        delete thread;
    }

    return NULL;
}


void Thread::start()
{
    pthread_create(&threadId_,NULL, threadRoutine,this);
}


void Thread::join()
{
    pthread_join(threadId_, NULL);
}


void Thread::setAutoDelete(bool autoDelete)
{
    autoDelete_ = autoDelete;
}

View Code
在主函数中调用方法也很简单:


#include "thread.h"
#include 
#include 
#include 
using namespace std;

void ThreadFunc()
{
    cout << "ThreadFunc..." << endl;
}

void ThreadFunc2(int count)
{
    while( count_-- )
    {
        cout << "This is a test" << endl;
        sleep(1);
    }
}

class Foo
{
public:
    Foo(int count) : count_(count){    }

    void MemerFunc()
    {
        while( count_-- )
        {
            cout << "This is a test" << endl;
            sleep(1);
        }
    }
private:
    int count_;

};

int main(void)
{


    //Thread *t = new Thread(ThreadFunc);    
  
    //Thread *t = new Thread(boost::bind(ThreadFunc2,4));
    
    Foo foo(3);
    Thread *t = new Thread(boost::bind(&Foo::MemerFunc,&foo));

    t->setAutoDelete(true);
    t->start();
    t->join();

    //do other work....

}

View Code
在上面的例子中我们可以绑定不同的对象到Thread的构造函数中,这样就可以实现随着绑定的不同调用不同的函数。  

本文由职坐标整理并发布,了解更多内容,请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved