C++ 多线程框架(1):new 一下就启动一个线程

几年前写过一个c++++的多线程框架,虽然写完了,但是人一懒做了一次说明以后就没影了,最近把代码整理了一下,准备发到github上,在这里,再把这个框架总结一下吧。

多线程一直是编程中常见的问题,特别是在Linux的c++上,多线程的封装一直不是很好,当然,有很多第三方库可以用,比如boost之类的,但是我们有时候并不需要那么庞大的库,只需要一个轻量级的线程框架就行了,于是自己编了一个,目前只在Linux下用了,但是设计的时候是按照多平台来编的,如果你有需要,可以自己添加一些个类,把他变成一个windows平台获取其他平台的,比如eCos,Vxworks等等。。

对于多线程,我们需要的是把操作系统底层封装起来,让用户编写程序的时候更多的关注他的代码逻辑而不是线程之间的逻辑,最好是new一个类以后,就启动了一个线程,线程之间的通信也有相应的类封装起来,只要调用就行了。

根据这些,我们定义了一组基类,来封装各种多线程的接口

操作系统基类,该类主要定义了createThread函数来创建线程,该函数是纯虚函数,继承自它的类需要根据平台实现其功能

立即学习“C++免费学习笔记(深入)”;

class COperatingSystem  {      public:          COperatingSystem();          ~COperatingSystem();            virtual  bool createThread(CThread *mThread,unsigned long stack_size=8*1024)=0;          virtual void  sleepSec(unsigned long sec)=0;        protected:          CThread     *p_thread;  };

 

线程基类,定义了threadEntry来作为线程的入口,initializeThread来初始化线程,子类可以初始化不同的成员变量,mainLoop是纯虚函数,为线程的主函数,一般是一个while循环,子类必须实现该虚函数。

class CThread  {      public:          CThread(const char *m_thread_name);          ~CThread();           void threadEntry(CCountingSem *pSemaphore);        protected:          virtual bool initializeThread();          virtual void mainLoop()=0;            COperatingSystem        *p_opration_system;          char        *p_thread_name;  };

为了平台的无关性,使用了简单工厂模式,用来根据不同的平台返回不同的操作系统类,信号量类和互斥类。

class COperatingSystemFactory  {      public:          static COperatingSystem *newOperatingSystem();          static CCountingSem  *newCountingSem(unsigned int init);          static CMutex           *newMutex(const char *pName=NULL);  };

信号量基类,纯虚函数定义了get和post信号量方法,子类必须根据系统类型进行不同的实现

class CCountingSem  {      public:          CCountingSem();          ~CCountingSem();           virtual bool                Get(Mode mode = kForever, unsigned long timeoutMS = 0) = 0;               virtual bool                Post(void) = 0;  };

互斥基类,纯虚函数定义了lock和unlock两个方法,同样,子类必须根据系统类型进行不同的实现

class CMutex  {      public:          CMutex(const char *pName = NULL);          ~CMutex();          virtual bool Lock()=0;          virtual bool UnLock()=0;        protected:          char       *mutex_name;  };

还有一个重头是msgQueue类,下次说。

有了这些个基础类以后,我们就可以开始了。

我们希望的结果是

用户,也就是程序员啦,从CThread继承一个自己的线程类,比如CTestThread,然后实现mainLoop方法,这样,一个不考虑通信的线程就编写完了,然后我只需要在main.cpp中new一下这个CTestThread,那么线程就启动了,没有其他任何繁琐的操作。

要实现这样的功能,上面那些个类需要怎么样的组合调用呢?

首先,因为是在Linux下,所以所有的基类都要派生出Linux对应的子类(CThread不需要,因为是用户编写的,COperatingSystemFactory也不需要,因为是抽象工厂),所以,我们在Linux下创建了CLinuxMutex,CLinuxOperratingSystem,CLinuxCountingSem三个子类,并且在这些个子类中实现了基类中的纯虚函数。

接着,我们new 一个 CTestThread 后,需要通过COperatingSystemFactory的newOperatingSystem 生成一个CLinuxOperratingSystem,然后CLinuxOperratingSystem调用createThread产生一个线程函数,然后把CTestThread的mainLoop绑定到这个线程函数中。

对,就这么简单

在github中下载了所有的文件以后,你只需要编写你自己的线程类,如:

class TestThread:public CThread  {      public:          TestThread(const char *m_name);          ~TestThread();          virtual void mainLoop();  };  //然后实现mainLoop方法:  void TestThread::mainLoop()  {      while(1)          {              printf("%s :hello world\n",p_thread_name);                        }  }

然后在main.cpp中,调用一句话new一下这个类:

TestThread *a=new TestThread("Thread A");

OK,一切搞定,现在运行,就能不停的打出hello world了。

同样,你也可以new多个实例

如果想要其他功能的线程,你再从CThread派生一个其他类就行了,很简单吧。

稍微复杂一点的是线程通信,下次说。

代码还没有整理完成,等整理完成了一并传到github上,大概还需要两三天时间吧。

github地址:

https://github.com/wyh267/Cplusplus_Thread_Lib

以上就是C++ 多线程框架(1):new 一下就启动一个线程的内容,更多相关内容请关注PHP中文网(www.php.cn)!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1432036.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月17日 06:08:16
下一篇 2025年12月14日 03:04:35

相关推荐

  • 从0自学C#01–自绘窗体边框

    主要介绍自绘窗体边框和背景颜色逐级变浅(深)。 1.先设置窗体为无边框模式 this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; 也可以右击窗体,选择属性,找到FormBorderStyler设置为None。此时窗体右上角…

    好文分享 2025年12月17日
    000
  • 从0自学C#02–子线程访问主线程(UI线程)控件

    如果使用多线程处理来提高 windows 窗体应用程序的性能,则你必须确保以线程安全的方式调用控件。 访问 Windows 窗体控件不是本身就线程安全的。如果有两个或两个以上线程操作控件的状态,则可能迫使该控件处于不一致状态。可能出现其他与线程相关的 bug,例如争用条件和死锁。请务必确保以线程安全…

    2025年12月17日
    000
  • 从0自学C#03–文件流保存数据为txt/excel格式

    主要介绍datatable、日志log、文件流filestream、streamwriter类,将数据保存为txt和excel格式。 1.创建TestDataTable类 CreateTable()方法创建一个数据table,SaveTableToExcel(string fileName)方法将数…

    好文分享 2025年12月17日
    000
  • 从0自学C#04–特性和设计原则

    1.三大特性 封装:隐藏内部实现。 继承:复用现有代码。 多态:改写对象行为。 2.设计原则 单一职责原则 Single Responsibility Principle(SRP) 一个类仅有一个引起它变化的原因。 开闭原则 Open-Close Principle(OCP) : 类模块应该是可扩展…

    好文分享 2025年12月17日
    000
  • C#学习日记27—-属性

    属性可以是 类(class)、结构(struct)、接口(interface)的命名成员,他提供灵活的机制来读取、写入、或计算私有(private)字段的值,属性可以看作是公共(public)字段的成员,但他实际上是定义了一个“访问器”的特殊方法让私有字段的值可以被读写或操作。    说的形象点吧,…

    2025年12月17日
    000
  • C#学习日记28—索引器、重载索引器

      索引器允许类或者结构的实例就像数组一样进行索引,当您为一个类定义一个索引器时,这个类就会像一个数组一样,您可以使用数组访问符 ‘[]’ 对该类的实例进行访问.. 索引器与 属性  类似,但是索引器要采用参数,(也可以这么认为,索引器是一个类的属性,同样也是通过访问器(一种…

    2025年12月17日
    000
  • C#学习日记29—-二维索引器 与 foreach遍历索引器

    上一篇结尾的时候我留下了几个问题,因为要断电了没有解决,这一篇我们继续上一篇的内容。点这里回到上一篇 问题1:         数组有多维度的,索引器也可以是多维的吗???          索引器可以是多维的,上一篇中我们定义的索引器只是一维索引器,同数组一样可以定义多维索引器。比如我们索引电影院…

    2025年12月17日
    000
  • C#学习日记20—-static静态变量 与 常量

     在上一篇  委托(delegate)类型     中我定义public方法的时候使用了 static 关键字,导致后来无法通过 对象.方法名  的形式访问此方法,这一篇我们就具体学习下 static 静态变量。   变量:       在学习static静态变量之前,我们还是有必要来了解 变量 的…

    2025年12月17日
    000
  • C#学习日记22—多重继承

       继承是面向对象程序设计中最重要的概念之一。继承允许我们根据一个类来定义另一个类来定义一个类,一个类从另一个类派生出来时,派生类从基类那里继承特性          继承的思想实现了 属于(IS-A) 关系。例如,哺乳动物 属于(IS-A) 动物,狗属于(IS-A) 哺乳动物,因此狗 属于(IS…

    2025年12月17日
    000
  • C#学习日记23—多态性 之 运算符重载、方法重载、抽象类、虚方法

         在c#中多态性的定义是:同一操作作用于不同类的实例,不同的类进行不同的解释,最后产生不同的执行结果。换句话说也就是 一个接口,多个功能。 C# 支持2种形式的多态性: 编译时的多态性、运行时的多态性 编译时的多态性:    编译时的多态性是通过重载来实现的 方法重载    您可以在同一个范…

    2025年12月17日
    000
  • C#学习日记24—-事件(event)

      事件为类和类的实例提供了向外界发送通知的能力,实现了对象与对象之间的通信,如果定义了一个事件成员,表示该类型具有 1.能够在事件中注册方法 (+=操作符实现)。 2.能够在事件中注销方法(-=操作符实现)。 3.当事件被触发时注册的方法会被通知(事件内部维护了一个注册方法列表)。委托(deleg…

    2025年12月17日
    000
  • C#学习日记21—-封装 与 访问修饰符

    封装:        被定义为”把一个或多个项目封闭在一个物理的或者逻辑的包中”。在面向对象程序设计方法论中,封装是为了防止对实现细节的访问。也就是把里面实现的细节包起来,这样很复杂的逻辑经过包装之后给别人使用就很方便,别人不需要了解里面是如何实现的,只要传入所需要的参数就可…

    2025年12月17日 好文分享
    000
  • C#学习日记26—接口(interface)类型

     接口包含类或结构可以实现的一组相关功能的定义例如,使用接口可以在类中包括来自多个源的行为。由于c#语言不支持多重继承,但是可以通过接口来实现多重继承  。简言之,接口只包含了成员(属性、事件、索引器)的声明。成员的定义具体怎么实现由他的派生类决定。   声明一个接口:     接口使用interf…

    2025年12月17日
    000
  • C#学习日记14—引用类型 之 object类

         先让我们了解下什么叫object类 Object类:        object类是所有类型的基类,所有类型都是由他派生而来,C#中所有的类都是直接或间接的从Sytem.Object类中继承,(可能有点迷糊,没关系,举个例子,如果Object类是树干,我们前面所学的所有类就是 树枝 或者 …

    2025年12月17日
    000
  • C#学习日记15—-引用类型 之 string类型用法总结

         c#中定义了一个基本的类string,专门用于对字符串的操作,同样这个类也是在.net框架结构的名字空间system中定义的,是system.string的别名。字符串的用法十分广泛,在类的定义中封装了许多内部的操作,我们只需要简单的利用就可以了。 创建一个string对象:       …

    好文分享 2025年12月17日
    000
  • C#学习日记16—-隐式转换具体用例

       经过前面的学习c#中基本的数据类型就介绍的差不多了,下面就学习下类型之间的互相转换.c# 中类型转换可以分为2类: 隐式转换 和 显式转换. 隐式转换:          隐式转换是系统默认的转换,不需要申明就可以进行转换。在隐式转换过程中,编译器无需对转换进行检查就能够安全的执行转换,比如从…

    2025年12月17日
    000
  • C#学习日记17—显示类型转换具体用例

       在c#的类型转换中,除了上一篇中介绍到的 隐式类型转换 外还有一种需要我们声明的类型转换—–显示类型转换.       显示类型转换,又叫强制类型转换,在进行转换的时候它需要我们明确的指定转换类型.  比如,当我们把long类型转换为int类型时,由于这种转换是丢失精度…

    2025年12月17日
    000
  • C#学习日记18—-装箱(boxing)转换与拆箱(unboxing)转换

      经过前面的学习,我们基本能够实现值类型与值类型之间的转换,引用类型与引用类型之间的转换,但是值类型与引用类型(object)之间的转换又该怎么实现呢??    在C# 中,我们采用装箱来实现将值类型转换成引用类型,用拆箱实现将引用类型转换成值类型;换句话说,它可以实现从任何值类型、引用类型到Ob…

    2025年12月17日
    000
  • C#学习日记19—-引用类型 之 委托(Delegate) 类型

        对于代表(委托也是它)delegate类型的意义,前面 引用类型前言 (点击查看)  中已经介绍过了,这里就不再罗嗦了,简言之,委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,说白了就是可以把方法当作参数传递。所有的委托(delegate)都派生自system…

    2025年12月17日
    000
  • c#学习日记01–新手上路

       对于c#(sharp)说实话我也是刚开始自学,大二了我的主修其实是java,但是c#我也不会落下,从今天开始踏上自学c#之路! 一:认识C#与.NET        .NET/dotnet:一般指.Net Framework框架。是一种平台,一种技术。        C#:一种编程语言,它可以…

    好文分享 2025年12月17日
    000

发表回复

登录后才能评论
关注微信