原创文章,转载请注明出处:http://www.jb51.cc/article/p-raudppry-o.html

cocos2d-x引擎在内部实现了一个庞大的主循环,每帧之间更新界面,如果耗时的操作放到了主线程中,游戏的界面就会卡,这是不能容忍的,游戏最基本的条件就是流畅性,这就是为什么游戏开发选择C++的原因。另外现在双核手机和四核手机越来越普遍了,是时候使用多线程来挖掘硬件的潜力了。

1.环境搭建

cocos2d-x中的多线程使用pthread就可以实现跨平台,而且也不是很难理解。使用pthread需要先配置一下工程。右击工程----->属性----->配置属性---->链接器----->输入---->附加依赖项中添加pthreadVCE2.lib,如下图


接着添加附加包含目录,右击项目,属性----->C/C++---->常规----->附加包含目录加入pthread头文件所在的目录


这样,环境就搭建起来了。

2.多线程的使用

使用pthread来实现多线程,最重要的一个函数是

[cpp] view plain copy print ?
  1. PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid,//线程的标示
  2. const pthread_attr_t * attr,//创建线程的参数
  3. void *(*start) (void *),//入口函数的指针
  4. void *arg); //传递给线程的数据

在HelloWorldScene.h文件中

[cpp] view plain copy print ?
  1. pthread_t pidrun,pidgo;
  2. static void* th_run(void *r);
  3. static void* th_go(void *r);
定义了两个函数和两个线程的标识。

然后自定义了一个类,用于给线程传递数据。Student类如下:

[cpp] view plain copy print ?
  1. #pragma once
  2. #include <string>
  3. class Student
  4. {
  5. public:
  6. Student(void);
  7. Student(std::string name,int age,std::string sex);
  8. ~Student(void);
  9. std::string name;
  10. int age;
  11. std::string sex;
  12. };

源文件如下

[cpp] view plain copy print ?
  1. #include "Student.h"
  2. #include "cocos2d.h"
  3. Student::Student(void)
  4. {
  5. }
  6. Student::~Student(void)
  7. {
  8. cocos2d::cclog("delete data");
  9. }
  10. Student::Student(std::string name,std::string sex)
  11. {
  12. this->name=name;
  13. this->age=age;
  14. this->sex=sex;
  15. }
在退出菜单的回调函数中启动两个线程:

[cpp] view plain copy print ?
  1. void HelloWorld::menuCloseCallback(CCObject* pSender)
  2. {
  3. Student *temp=new Student(std::string("zhycheng"),23,std::string("male"));
  4. pthread_mutex_init(&mutex,NULL);
  5. pthread_create(&pidrun,NULL,th_run,temp);//启动线程
  6. pthread_create(&pidgo,th_go,0);
  7. }

可以看到,将Student的指针传递给了pidrun线程,那么在pidrun线程中获得Student信息如下:

[cpp] view plain copy print ?
  1. Student *s=(Student*)(r);
  2. cclog("name is %s,and age is %d,sex is %s",s->name.c_str(),s->age,s->sex.c_str());
  3. delete s;

3.线程同步

使用了线程,必然就要考虑到线程同步,不同的线程同时访问资源的话,访问的顺序是不可预知的,会造成不可预知的结果。

这里使用pthread_mutex_t来实现同步,下面我来演示一下使用多线程实现卖票系统。卖票的时候,是由多个窗口同时卖票,这里要做到一张票不要卖出去两次,不要出现有票却无法卖的结果。

在线程函数th_run和th_go中来卖票,票的数量是一个全局变量,每卖出去一张票,就将票的数量减一。其中同步的pthread_mutex_t也是一个全局变量,就用它来实现线程同步。

[cpp] view plain copy print ?
  1. void* HelloWorld::th_run(void *r)
  2. {
  3. Student *s=(Student*)(r);
  4. cclog("name is %s,s->sex.c_str());
  5. delete s;
  6. while(true)
  7. {
  8. pthread_mutex_lock(&mutex);
  9. if(ticket>0)
  10. {
  11. cclog("thread run sell %d",ticket);
  12. ticket--;
  13. pthread_mutex_unlock(&mutex);
  14. }
  15. else
  16. {
  17. pthread_mutex_unlock(&mutex);
  18. break;
  19. }
  20. Sleep(1);
  21. //Usleep(10);
  22. }
  23. return NULL;
  24. }

[cpp] view plain copy print ?
  1. void* HelloWorld::th_go(void *r)
  2. {
  3. while(true)
  4. {
  5. pthread_mutex_lock(&mutex);
  6. if(ticket>0)
  7. {
  8. cclog("thread go sell %d",ticket);
  9. ticket--;
  10. pthread_mutex_unlock(&mutex);
  11. }
  12. else
  13. {
  14. pthread_mutex_unlock(&mutex);
  15. break;
  16. }
  17. Sleep(1);
  18. }
  19. return NULL;
  20. }


mutex被锁定后,其他线程若再想锁定mutex的话,必须等待,当该线程释放了mutex之后,其他线程才能锁定mutex。Sleep()函数可以使得该线程休眠,单位是毫秒。下面是卖票的结果:

[cpp] view plain copy print ?
  1. name is zhycheng,and age is 23,sex is male
  2. delete data
  3. thread run sell 100
  4. thread run sell 99
  5. thread go sell 98
  6. thread go sell 97
  7. thread run sell 96
  8. thread go sell 95
  9. thread go sell 94
  10. thread run sell 93
  11. thread go sell 92
  12. thread run sell 91
  13. thread go sell 90
  14. thread go sell 89
  15. thread run sell 88
  16. thread go sell 87
  17. thread run sell 86
  18. thread go sell 85
  19. thread run sell 84
  20. thread go sell 83
  21. thread run sell 82
  22. thread go sell 81
  23. thread run sell 80
  24. thread go sell 79
  25. thread run sell 78
  26. thread go sell 77
  27. thread run sell 76
  28. thread go sell 75
  29. thread run sell 74
  30. thread go sell 73
  31. thread run sell 72
  32. thread go sell 71
  33. thread run sell 70
  34. thread go sell 69
  35. thread go sell 68
  36. thread run sell 67
  37. thread go sell 66
  38. thread run sell 65
  39. thread go sell 64
  40. thread run sell 63
  41. thread go sell 62
  42. thread run sell 61
  43. thread go sell 60
  44. thread run sell 59
  45. thread go sell 58
  46. thread run sell 57
  47. thread go sell 56
  48. thread run sell 55
  49. thread go sell 54
  50. thread run sell 53
  51. thread run sell 52
  52. thread go sell 51
  53. thread run sell 50
  54. thread go sell 49
  55. thread run sell 48
  56. thread go sell 47
  57. thread run sell 46
  58. thread go sell 45
  59. thread run sell 44
  60. thread run sell 43
  61. thread go sell 42
  62. thread run sell 41
  63. thread run sell 40
  64. thread go sell 39
  65. thread run sell 38
  66. thread run sell 37
  67. thread run sell 36
  68. thread run sell 35
  69. thread go sell 34
  70. thread run sell 33
  71. thread run sell 32
  72. thread go sell 31
  73. thread run sell 30
  74. thread run sell 29
  75. thread run sell 28
  76. thread run sell 27
  77. thread run sell 26
  78. thread run sell 25
  79. thread go sell 24
  80. thread run sell 23
  81. thread go sell 22
  82. thread go sell 21
  83. thread run sell 20
  84. thread go sell 19
  85. thread run sell 18
  86. thread run sell 17
  87. thread go sell 16
  88. thread run sell 15
  89. thread go sell 14
  90. thread go sell 13
  91. thread run sell 12
  92. thread go sell 11
  93. thread go sell 10
  94. thread run sell 9
  95. thread go sell 8
  96. thread run sell 7
  97. thread go sell 6
  98. thread go sell 5
  99. thread run sell 4
  100. thread go sell 3
  101. thread run sell 2
  102. thread run sell 1


可以看到,这个打印结果正确无误。如果不加mutex会是什么样的结果呢,我将线程同步的mutex注释掉,输出的结果为:

[cpp] view plain copy print ?
  1. name is zhycheng,sex is male
  2. delete data
  3. thread run sell 100
  4. thread run sell 99
  5. thread run sell 98
  6. thread go sell 97
  7. thread run sell 96
  8. thread go sell 95
  9. thread run sell 94
  10. thread go sell 94
  11. thread run sell 92
  12. thread run sell 91
  13. thread go sell 90
  14. thread run sell 89
  15. thread go sell 88
  16. thread run sell 87
  17. thread run sell 86
  18. thread go sell 86
  19. thread go sell 84
  20. thread run sell 83
  21. thread go sell 82
  22. thread run sell 81
  23. thread go sell 80
  24. thread run sell 79
  25. thread run sell 78
  26. thread go sell 77
  27. thread run sell 76
  28. thread run sell 75
  29. thread go sell 74
  30. thread run sell 73
  31. thread go sell 72
  32. thread run sell 71
  33. thread go sell 70
  34. thread go sell 69
  35. thread run sell 68
  36. thread go sell 67
  37. thread go sell 66
  38. thread run sell 65
  39. thread go sell 64
  40. thread go sell 63
  41. thread run sell 62
  42. thread go sell 61
  43. thread run sell 60
  44. thread run sell 59
  45. thread run sell 58
  46. thread run sell 57
  47. thread run sell 56
  48. thread run sell 55
  49. thread go sell 54
  50. thread run sell 54
  51. thread go sell 52
  52. thread run sell 52
  53. thread go sell 50
  54. thread run sell 50
  55. thread go sell 49
  56. thread run sell 47
  57. thread go sell 47
  58. thread go sell 45
  59. thread run sell 45
  60. thread run sell 43thread go sell 43
  61. thread run sell 41
  62. thread go sell 41
  63. thread go sell 39
  64. thread run sell 39
  65. thread run sell 37
  66. thread go sell 37
  67. thread go sell 35
  68. thread run sell 35
  69. thread go sell 33thread run sell 33
  70. thread go sell 31thread run sell 31
  71. thread go sell 29
  72. thread run sell 29
  73. thread go sell 27
  74. thread run sell 27
  75. thread go sell 25
  76. thread run sell 25
  77. thread run sell 23
  78. thread go sell 23
  79. thread run sell 21
  80. thread go sell 21
  81. thread go sell 19
  82. thread run sell 19
  83. thread run sell 17
  84. thread go sell 17
  85. thread go sell 15
  86. thread run sell 15
  87. thread run sell 13
  88. thread go sell 13
  89. thread run sell 11thread go sell 11
  90. thread go sell 9
  91. thread run sell 9
  92. thread run sell 7
  93. thread go sell 7
  94. thread go sell 5thread run sell 5
  95. thread go sell 3
  96. thread run sell 3
  97. thread go sell 1
  98. thread run sell 1


可以看到,有的票卖了两次,有的票就没卖。

4.注意

1.Sleep()函数是使得线程休眠的函数,这个函数不跨平台,仅仅在windows上能用,其他平台使用usleep。

2.在非主线程中不能使用cocos2d-x管理内存的CCObject::retain(),CCObject::release()CCObject::autorelease(),因为CCAutoreleasePool不是线程安全的,OPENGL的上下文也不是线程安全的,所以不要再非主线程中使用cocos2d-x的API和UI操作。


最后工程的源代码下载:http://download.csdn.net/detail/zhy_cheng/5600979

cocos2D-x游戏开发多线程的更多相关文章

  1. iOS:核心图像和多线程应用程序

    我试图以最有效的方式运行一些核心图像过滤器.试图避免内存警告和崩溃,这是我在渲染大图像时得到的.我正在看Apple的核心图像编程指南.关于多线程,它说:“每个线程必须创建自己的CIFilter对象.否则,你的应用程序可能会出现意外行为.”这是什么意思?我实际上是试图在后台线程上运行我的过滤器,所以我可以在主线程上运行HUD(见下文).这在coreImage的上下文中是否有意义?

  2. ios – 多个NSPersistentStoreCoordinator实例可以连接到同一个底层SQLite持久性存储吗?

    我读过的关于在多个线程上使用CoreData的所有内容都讨论了使用共享单个NSPersistentStoreCoordinator的多个NSManagedobjectContext实例.这是理解的,我已经使它在一个应用程序中工作,该应用程序在主线程上使用CoreData来支持UI,并且具有可能需要一段时间才能运行的后台获取操作.问题是NSPersistentStoreCoordinator会对基础

  3. ios – XCode断点应该只挂起当前线程

    我需要调试多线程错误.因此,为了获得生成崩溃的条件,我需要在代码中的特定点停止一个线程,并等待另一个线程到达第二个断点.我现在遇到的问题是,如果一个线程遇到断点,则所有其他线程都被挂起.有没有办法只停止一个线程,让其他线程运行,直到它们到达第二个断点?)其他更有趣的选择:当你点击第一个断点时,你可以进入控制台并写入这应该在该断点处暂停当前上下文中的线程一小时.然后在Xcode中恢复执行.

  4. ios – 在后台线程中写入Realm后,主线程看不到更新的数据

    >清除数据库.>进行API调用以获取新数据.>将从API检索到的数据写入后台线程中的数据库中.>从主线程上的数据库中读取数据并渲染UI.在步骤4中,数据应该是最新数据,但我们没有看到任何数据.解决方法具有runloops的线程上的Realm实例,例如主线程,updatetothelatestversionofthedataintheRealmfile,因为通知被发布到其线程的runloop.在后台

  5. ios – NSURLConnectionLoader线程中的奇怪崩溃

    我们开始看到我们的应用启动时发生的崩溃.我无法重现它,它只发生在少数用户身上.例外情况是:异常类型:EXC_BAD_ACCESS代码:KERN_INVALID_ADDRESS位于0x3250974659崩溃发生在名为com.apple.NSURLConnectionLoader的线程中在调用时–[NSBlockOperationmain]这是该线程的堆栈跟踪:非常感谢任何帮助,以了解可能导致这种崩

  6. ios – 合并子上下文时的NSObjectInaccessbileExceptions

    我尝试手动重现,但失败了.是否有其他可能发生这种情况的情况,是否有处理此类问题的提示?解决方法在创建子上下文时,您可以尝试使用以下行:

  7. ios – 从后台线程调用UIKit时发出警告

    你如何处理项目中的这个问题?

  8. ios – 在SpriteKit中,touchesBegan在与SKScene更新方法相同的线程中运行吗?

    在这里的Apple文档AdvancedSceneProcessing中,它描述了更新方法以及场景的呈现方式,但没有提到何时处理输入.目前尚不清楚它是否与渲染循环位于同一个线程中,或者它是否与它并发.如果我有一个对象,我从SKScene更新方法和touchesBegan方法(在这种情况下是SKSpriteNode)更新,我是否要担心同步对我的对象的两次访问?解决方法所以几天后没有回答我设置了一些实验

  9. ios – 在后台获取中加载UIWebView

    )那么,有一种方法可以在后台加载UIWebView吗?解决方法如果要从用户界面更新元素,则必须在应用程序的主队列(或线程)中访问它们.我建议您在后台继续获取所需的数据,但是当需要更新UIWebView时,请在主线程中进行.你可以这样做:或者您可以创建一个方法来更新UIWebView上的数据,并使用以下方法从后台线程调用它:这将确保您从正确的线程访问UIWebView.希望这可以帮助.

  10. ios – 何时使用Semaphore而不是Dispatch Group?

    我会假设我知道如何使用DispatchGroup,为了解问题,我尝试过:结果–预期–是:为了使用信号量,我实现了:并在viewDidLoad方法中调用它.结果是:从概念上讲,dispachGroup和Semaphore都有同样的目的.老实说,我不熟悉:什么时候使用信号量,尤其是在与dispachGroup合作时–可能–处理问题.我错过了什么部分?

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部