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一个你的类对象就可以了。

 

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

[Socket]基于C++的纯面向对象的通用高性能大并发TCP-SERVER/CLIENT开发框架

1. 前言 本篇主要介绍Servant和Client都会使用到的公共基础,主要包括两大部分:一是对线程相关的封装;另是对Socket相关的封装。这些基础类间的关系比较简单,但是和Server/Cli...
  • yfhy2014
  • yfhy2014
  • 2015年03月11日 18:27
  • 2780

C++多线程框架(三)--------- 消息队列

首先,本文提到的代码的github地址为: https://github.com/wyh267/Cplusplus_Thread_Lib 之前,多线程一些基本的东西,包括线程创建,...
  • ygrx
  • ygrx
  • 2013年05月23日 13:19
  • 20014

laravel框架中所蕴含的两个重要的面向对象设计模式

学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家...
  • qq_31989521
  • qq_31989521
  • 2016年06月11日 10:55
  • 3327

MFC C++ 中面向对象的多线程实现

参加了交通运输学院的一个交通科技大赛,需要与硬件沟通,当然也不是什么好高端的玩意儿,就是一个名为sick的一个德国产的激光扫描仪的使用,叫什么LMS-511;也就是基于TCP/IP通讯的罢了;主要是通...
  • u012706436
  • u012706436
  • 2014年03月09日 00:05
  • 748

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

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

linux C++ 面向对象线程类(封装,继承,多态)

头文件Thread.h#ifndef _THREAD_H_ #define _THREAD_H_ #include //抽象类 class Thread { public: Thread();...
  • u011676589
  • u011676589
  • 2013年08月15日 09:19
  • 2493

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

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

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

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

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

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

【Linux C/C++】 第08讲 多线程TCP传输文件/select模型

多线程TCP传输文件/select模型
  • Nanhu2012
  • Nanhu2012
  • 2017年07月23日 09:47
  • 367
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux C++面向对象多线程机制实现框架
举报原因:
原因补充:

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