Cocos2d-x優化中多線程併發訪問

多線程併發訪問在Cocos2d-x引擎中用的不是很是多,這主要是因爲中整個結構設計沒有採用多線程。

源自於Objective-C的Ref對象,需要使用AutoreleasePool進行內存管理,AutoreleasePool是非線程安全的,所有不推薦在子多線程中調用Ref對象的retain()、 release()和autorelease()等函數。另外,OpenGL上下文對象也是不支持線程安全的。php


但是有的時候咱們需要異步載入一些資源,好比:載入圖片紋理、聲音的預處理和網絡請求數據等。html

假設是異步載入圖片紋理咱們可以使用第20.4.4一節介紹的內容。但聲音的預處理和網絡請求數據等就需要本身經過多線程技術實現了。
Cocos2d-x引擎也提供了多線程技術。Cocos2d-x 3.x以前是使用第三方的pthread技術。ios

Cocos2d-x 3.x以後使用C++11新規範中的std::thread多線程技術,std::thread使用起來比較簡單。


1.std::thread多線程技術
std::thread是C++11 引入了一個新的線程庫。它提供了線程管理相關函數。std::thread庫中還提供了std::mutex(相互排斥量)。經過std::mutex可以實現線程同步。
啓動一個新的線程很是easy。當咱們建立一個 std::thread 對象時候,它便會自行啓動。建立線程std::thread 對象時。可以提供該線程的回調函數。如下代碼實現了建立線程和線程函數的回調:
安全

#include <thread>
#include <iostream>


void callfn(){																①
    std::cout << "Hello thread! " << std::endl;
}
int main(){
    std::thread t1(callfn);												②
		t1.join();																③
    return 0;
}


上述代碼第②行是建立t1線程對象。它的參數是函數指針callfn,假設需要。咱們還可以爲回調函數提供參數。

代碼第①行是回調函數的定義。第③行代碼t1.join()是將子線程與主線程合併,這樣的合併可以使子線程運行完畢後才幹繼續運行主線程,這是爲了不子線程還在運行,主線程已經運行結束而撤銷。微信


建立線程還可以使用堆的方式分配內存,代碼例如如下: 
網絡

void callfn(){
    std::cout << "Hello thread! " << std::endl;
}
int main(){
    std::thread* t1 = new  std::thread(callfn);									①
	t1->join();
	delete	t1;																②
	t1 = nullptr;															③
    return 0;
}


上述代碼第①行是經過堆方式分配內存,即經過new運算符建立動態線程對象。所以需要在使用完畢的狀況下釋放對象。咱們在代碼第②行使用delete t1語句釋放,釋放完畢還以經過代碼第③行t1 = nullptr設置指針變量,這樣可以防止「野指針」。


2.異步預處理聲音
std::thread線程Cocos2d-x中有很是多現實的應用。異步預處理聲音,異步載入一些資源資源文件。異步載入圖片紋理Cocos2d-x爲咱們提供了API,但是它們異步載入需要咱們本身實現。

如下咱們介紹一下異步預處理聲音。多線程


咱們在前面20.5一節介紹了聲音預處理和清除,在那一節中預處理聲音是同步的。它會致使阻塞主線程,使用戶的感受會「卡」了一下。假設這個「卡」比較長。咱們解決主線程阻塞問題。改善用戶體驗,咱們可以異步預處理聲音。
咱們在20.5一節的案例中採用std::thread線程異步預處理聲音,咱們可以在AppDelegate中進行異步載入,改動以後的AppDelegate.h代碼例如如下:
#include "cocos2d.h"
#include "SimpleAudioEngine.h"


using namespace CocosDenshion;


class  AppDelegate : private cocos2d::Application
{
private:
std::thread *_loadingAudioThread;
void loadingAudio();


public:
AppDelegate();
virtual ~AppDelegate();
 
   … …
};
咱們在第①行聲明瞭私有的std::thread線程指針變量_loadingAudioThread。第②代碼是聲明瞭私有的異步預處理聲音函數loadingAudio()。
改動以後的AppDelegate.cpp代碼例如如下:
併發

include "AppDelegate.h"
#include "HelloWorldScene.h"


USING_NS_CC;


AppDelegate::AppDelegate() 
{
	_loadingAudioThread = new std::thread(&AppDelegate::loadingAudio,this);				①
}


AppDelegate::~AppDelegate() 
{
	_loadingAudioThread->join();											②
	CC_SAFE_DELETE(_loadingAudioThread);									③
}


bool AppDelegate::applicationDidFinishLaunching() {
   … …
	return true;
}
void AppDelegate::applicationDidEnterBackground() {
	Director::getInstance()->stopAnimation();
	SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
}
void AppDelegate::applicationWillEnterForeground() {
	Director::getInstance()->startAnimation();
	SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
}


void AppDelegate::loadingAudio()											④
{
	//初始化 音樂
	SimpleAudioEngine::getInstance()->preloadBackgroundMusic("sound/Jazz.mp3");
	SimpleAudioEngine::getInstance()->preloadBackgroundMusic("sound/Synth.mp3");
	//初始化 音效
	SimpleAudioEngine::getInstance()->preloadEffect("sound/Blip.wav");
}


上述代碼第①行是在構造函數裏建立線程對象。建立線程對象代碼也可以放置到 AppDelegate::applicationDidFinishLaunching()函數中,咱們依據需要在合適的地方建立。
第②行代碼_loadingAudioThread->join()是合併線程到主線程,這個處理是在析構函數中調用的,join()函數一般是在線程處理完畢後調用,咱們可以在析構函數中調用。也可以在一些退出函數(如Layer的onExit函數)中調用。由於是_loadingAudioThread動態對象指針類型,需要釋放對象,咱們可以經過第③行代碼CC_SAFE_DELETE(_loadingAudioThread)釋放。CC_SAFE_DELETE宏的做用例如如下:
delete _loadingAudioThread;
_loadingAudioThread = nullptr;

第④行代碼AppDelegate::loadingAudio() 定義了線程回調函數。咱們在這個函數中預處理聲音。app


不少其它內容請關注最新Cocos圖書《Cocos2d-x實戰 C++卷》
本書交流討論站點: http://www.cocoagame.net
不少其它精彩視頻課程請關注智捷課堂Cocos課程: http://v.51work6.com
歡迎增長Cocos2d-x技術討論羣:257760386


《Cocos2d-x實戰 C++卷》現已上線。各大商店均已開售:異步

京東:http://item.jd.com/11584534.html

亞馬遜:http://www.amazon.cn/Cocos2d-x%E5%AE%9E%E6%88%98-C-%E5%8D%B7-%E5%85%B3%E4%B8%9C%E5%8D%87/dp/B00PTYWTLU

噹噹:http://product.dangdang.com/23606265.html

互動出版網:http://product.china-pub.com/3770734

《Cocos2d-x實戰 C++卷》源代碼及樣章下載地址:

源代碼下載地址:http://51work6.com/forum.php?mod=viewthread&tid=1155&extra=page%3D1 

樣章下載地址:http://51work6.com/forum.php?

mod=viewthread&tid=1157&extra=page%3D1

歡迎關注智捷iOS課堂微信公共平臺
相關文章
相關標籤/搜索