关闭

Linux C++面向对象多线程机制实现框架

1153人阅读 评论(0) 收藏 举报

多线程程序主要分为一下两个部分,1.线程部分,2.线程通讯部分

线程部分包括线程的创建,启动,运行。

线程通讯部分包括线程间的数据交换,消息发送,以及线程内部的数据交换和消息发送

 

一,线程部分

线程部分主要功能是线程的创建,启动和运行

在基本的linux中,线程的创建实际上只要一个函数就可以实现

int pthread_create(pthread_t *tid, const pthread_attr_t *tattr, void *(*start_routine)(void *), void *arg);
返回值:函数成功返回0。任何其他返回值都表示错误。
创建一个线程。
参数tattr中含有初始化线程所需要的属性,start_routine是线程入口函数的地址,当start_routine返回时,相应的线程就结束了。
当函数成功时,线程标示符保存在参数tid指向的内存中。
如果不指定属性对象,将其置为NULL,则创建一个缺省的线程,有如下属性:
非绑定的;
未分离的;
由一个缺省大小的堆栈;
具有和父线程一样的优先级。
注意:在创建子线程时,传给子线程的输入参数最好是由malloc()函数返回的指针或指向全局变量的指针,而不要是指向局部变量的指针。要保证子线程处理参数时,该区域仍然有效。 

因为我们所说的是面向对象模式下的多线程编程,所以,势必要把线程的创建,启动,运行封装到一个线程类(class Thread)中,当我们启动自己的线程的时候,只需要继承这个类,然后重载这个类中的主函数就可以了,编写者可以把自己的精力都放到具体的业务逻辑中去。

 

 

 

为了封装这个类,也为了跨平台的实现,我们封装线程类用到了三个类,分别是

1.       Thread    负责线程的具体逻辑

2.       OS          负责线程的创建,操作系统的底层调用都在这个类中,如pthread_create

3.       OSFactory      设计模式中“简单工厂”类,负责OS的创建,可以根据不同平台创建不同的OS

 

这三个类都是与平台无关的类,是最高层的抽象,只有几个最基础的方法和虚函数。

 

OS类下面可以进行继承,来具体实现不同的平台(Linux,Win32,vxworks,OS2….),我们这里以Linux为例,所以在OS类之下要继承出LinuxOS,来具体实现线程的创建等函数。

 

Thread类下面可以继承出自己想实现的具体功能的线程类。如A1Thread,A2Thread等。

 

首先来看Thread类,该类描述如下:

 

class Thread
...{
public:
    Thread();        
//构造函数
    virtual ~Thread();  //析构函数
     void ThreadEntry(); //线程入口点
 protected:
    
virtual void Run(void= 0;   //主函数,继承类重载此方法
    virtual bool Initialize(void);  //初始化,继承类重载此方法
virtual void Deinitialize(void); //退出前析构,继承类重载此方法

    OS 
*fOS;     //OS对象,用来启动线程
private:
    Thread(
const Thread &otherInstance);
    Thread 
& operator = (const Thread &otherInstance);
}
;

 

线程类构造

 

Thread::Thread()
...{
    fOS 
= OSFactory::NewOS();     //返回一个OS对象
if (fOS== NULL)
    
...{
        printf(
"Fatal Error: CnlThread::CnlThread() : Failed to create OS instance! ");
}

if (!fOS->CreateThread(this,20*1024))  //使用fOS开始创建线程
    ...{
        printf(
"CnlA1Thread Failed to spawn thread! ");
    }

}

 

线程入口点:入口点中的三个函数是你唯一要根据自己的程序要求要修改的地方。

void Thread::ThreadEntry()
 
...{
       
bool result;
       Initialize();    
//初始化
    Run();        //运行
    Deinitialize();  //析构
}


 

OS类描述如下:

class OS
...{
public:
       OS();            
//构造函数
   virtual ~OS();      //析构函数
   virtual bool CreateThread(Thread *pThread,unsigned long StackSize=8*1024)=0;//创建线程

private:
    OS(OS 
&otherInstance);
    OS 
&operator =(OS &otherInstance);

protected:
       Thread 
*fThread;  //线程对象
}
;

 

LinuxOSOS继承而来,描述如下:

class LinuxOS: public OS
...{
public:
       LinuxOS();
       
virtual ~LinuxOS();
       
virtual bool CreateThread(Thread *pThread,unsigned long StackSize=8*1024);

private:
       LinuxOS(LinuxOS 
&otherInstance);
       LinuxOS 
& operator = (LinuxOS &otherInstance);

     sem_t mSuspendSem;
    pthread_t mThreadId;
// POSIX 线程 id
  pthread_attr_t mThreadAttr;// 线程属性对象
}
;

 

CreateThread方法负责启动一个新的线程,程序如下:

bool LinuxOS::CreateThread(Thread * pThread, unsigned long StackSize)
...{
     
int rc;
    unsigned 
int arguments[4];
    
bool result;
    
if (pThread == NULL)
    
...{
              printf(
"LinuxOS::CreateThread() : Thread pointer is NULL!  Can't begin the thread... ");
               
return false;
    }

    fThread 
= pThread;
   pthreadc
=pThread;      //pthreadc是全局变量,标示当前需要启动的线程类
 pthread_attr_init(&mThreadAttr);  //线程属性初始化
 memset(arguments, 0sizeof(arguments));
  arguments[
0= (unsigned long) pThread;   //参数传递
 rc = pthread_create(&mThreadId, &mThreadAttr, (void * (*) (void *))ThreadEntrypoint, arguments);      //启动ThreadEntrypoint函数创建实在线程
    if (rc != 0)...{            
                      printf(
"LinuxOS::CreateThread() : Failed to create and start the thread! ");
                      fThread 
= NULL;
                     mThreadId 
= 0;
                    
return false;
    }

   pthread_detach(mThreadId);
    
return true;
}


 

 

ThreadEntrypoint函数描述如下,该函数不属于任何类

void ThreadEntrypoint(unsigned long *threadParm)
...
    
if (pthreadc == NULL)
    
...{
    printf(
"ThreadEntrypoint:  ERROR - thread pointer is NULL!  Can't start the thread! ");
    }

    
else
    
...{
        pthreadc
->ThreadEntry();   //进入到线程类的入口点,准备运行run()
    }

    pthread_exit(
0);
}


 

 

OSFactory描述如下:

class OSFactory
...{
public:
       OSFactory();
       
virtual ~OSFactory();
       
static OS *NewOS();   //创建相应的OS对象

private:
    OSFactory(OSFactory 
&otherInstance);
    OSFactory 
& operator =(OSFactory &otherInstance);
}
;

 

static OS *NewOS()方法描述如下:

 

 

OS *OSFactory::NewOS(void)
...{
#ifdef (__linux__)
    
return new LinuxOS();  //根据需要返回不同类型的OS对象,我们这里是LinuxOS
#endif
#ifdef (__win32__)
       
return new Win32OS();  //这个可以根据操作系统的不同继承OS类来得到新类
#endif
}


 

 

至此,我们的面向对象多线程框架已经搭起来了,下面要做的就是你根据自己的需要,从Thread继承一个线程类,然后重载run方法,来实现你的功能。

 

最后,在整个程序的main函数中添加如下两句话就可以了

int main()
...{
       ThreadA 
*pA;
       pA
=new ThreadA();
       sleep(
3);
       ThreadB
*pB;
       pB
=new ThreadB();
       
while(1)
              ;
}

 

这样,就创建了两个线程ThreadAThreadB,并且这两个线程可以很好的跑起来了,只是他们之间还不能通讯,通讯是我们接下来要讲的事情了。

 

我们看看ThreadA是怎么跑起来的啊

1.pA=new ThreadA()调用ThreadA的构造函数,由于构造函数我们没有重写,所以是调用的Thread的构造函数

2.Thread的构造函数通过调用fOS = OSFactory::NewOS()返回了一个LinuxOS对象

3. 然后构造函数继续调用fOS->CreateThread(this,20*1024) 开始创建线程,并把自己(this),也就是ThreadA传入到参数中

4.CreateThreadpthreadc=pThread;ThreadA赋值给全局变量pthreadc,然后调用线程创建函数pthread_create跳入到ThreadEntrypoint,此时,线程已经起来了

5.在ThreadEntrypoint中调用pthreadc->ThreadEntry()调用了ThreadA的线程入口点函数

6. ThreadEntry没有被重载,所以依次执行Initialize();Run();Deinitialize();这三个函数,而这三个函数是ThreadA重载的,所以开始执行你自己的方法了。

 

按照上面的顺序我们可以知道,如果按照这个框架来跑多线程,你唯一要做的就是从Thread类继承一个你自己类,然后重载Initialize();Run();Deinitialize();来实现你具体要实现的功能,最后在main函数中new一个你的类对象就可以了。

 

目前这样只是能按照一个类就是一个线程的模式跑多个线程,而线程之间还不能通讯,后面我们将慢慢添加这个框架,使线程之间可以互相通讯,我们目的是多线程和面向对象。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:1706294次
    • 积分:19617
    • 等级:
    • 排名:第440名
    • 原创:27篇
    • 转载:1525篇
    • 译文:2篇
    • 评论:128条
    最新评论