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

转载 2012年03月21日 21:41:22

多线程程序主要分为一下两个部分,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一个你的类对象就可以了。

 

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

相关文章推荐

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

1.封装遇到的问题 将pthread线程封装为抽象类,这样用户在使用线程时,只需要继承一下这个抽象类,并实现相应的接口就可以了。这样做的好处是 用户可以将注意力集中在线程所要执行的逻辑上,而不需要关注...

key-value 多线程服务器的Linux C++实现

项目需求 总体思路 网络通信 字符解析 数据存储与查询 1 存储管理 2 数据查询 多线程 待改进 GitHub源码项目需求 设计一个基于Socket或基于HTTP的服务器,服务内容是提供一种简单...

C++多线程面向对象解决方案

相信很多人都读过《C++沉思录》这本经典著作,在我艰难地读完整本书后,留给我印象最深的只有一句话::“用类表示概念,用类解决问题”。 关于多线程编程,如果不是特别需要,大多数开发人员都不会特意去触碰...
  • qsycn
  • qsycn
  • 2012年04月26日 09:45
  • 570

Linux C/C++多线程pthread实例

inux中C/C++开发多线程程序多遵循POSIX线程接口(也就是pthread),pthread涉及函数很多个(更多参见pthread.h头文件),常用的有pthread_create、pthrea...

linux c++ 多线程 互斥访问

from: http://blog.csdn.net/chexlong/article/details/7058283 //锁接口类 class ILock { public: ...
  • cl11010
  • cl11010
  • 2013年11月23日 12:26
  • 623

linux C++多线程操作文件&输出加锁

下述demo将指定目录下文件存入vector,然后一分为二交给两个线程(threadTask1,threadTask2)去分别处理,对输出函数printDirent加锁防止紊乱。#include #...
  • undoner
  • undoner
  • 2016年05月03日 15:22
  • 1769

Linux C/C++多线程学习:生产者消费者问题

生产者消费者问题 多个生产者和多个生产者的问题。生产者不断的向仓库放入产品,消费者不断的从仓库取出产品,仓库的容量是有限的。因此,当仓库处于满状态时,生产者必须等待消费者取出 1 个或多个产品后才能...
  • ywcpig
  • ywcpig
  • 2016年09月20日 18:55
  • 1112

新手学C++多线程编程(9)多线程面向对象架构和类层次C++组件

C++多线程编程(9)多线程面向对象架构和类层次C++组件   转载▼ C++多线程编程(9) 多线程面向对象架构和类层次C++组件   1.软件片段的...

Linux c 贪吃蛇 无curses、多线程、信号的实现

Linux c 贪吃蛇现有的多是借助 curses库、信号、多线程等技术实现的 这一版没有哦!...
  • Lc_Xs
  • Lc_Xs
  • 2017年04月07日 17:46
  • 241
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux C++面向对象多线程机制实现框架
举报原因:
原因补充:

(最多只允许输入30个字)