日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

使用C++11實現Android系統的Handler機制

瀏覽:182日期:2022-09-24 17:34:08

使用C++11實現Android系統的Handler機制

封面出自:板栗懶得很背景

線程作為系統的基礎資源,相信大多數讀者都有使用到。一般情況下我們會直接開一個線程做一些耗時操作,處理完之后讓線程自動結束,資源被系統回收。這種簡單粗暴的方法不少讀者、甚至一些大廠的APP都在用。以Java語言為例,我們可以直接new一個Thread對象,然后覆蓋run方法,最后調一下start方法便可以成功運行一個線程。如果我們每次異步做一些耗時處理都單獨開啟一個線程,比如異步加載網絡圖片這種高并發操作,每張圖片都開一個線程的話,必然會造成線程資源的浪費,而且也沒有很好的方法去處理跨線程通訊的問題。由于語言層面的低成本導致系統的線程資源被濫用,已經成為了一個很普遍的現象。

new Thread(){ @Override public void run() { //Do somethings }}.start()

Handler

  Handler機制通過開啟一個子線程,并進入死循環,不停消費其它線程發送過來的消息,從而達到跨線程通訊的目的。Handler主要用于跨線程通訊,但同時也能在一定程度上復用線程,是一種比較理想的線程使用方式。Android系統Handler主要包含以下三部分:

Handler Looper Message & MessageQueue

Handler顧名思義就是消息的處理類,同時也是消息發送的代理入口,通過調用Handler的相關接口發送一條消息,最終會被轉發到Looper,由Looper把Message加入到隊列的尾部。Looper是消息循環驅動的動力所在,我們規定同一個線程只能擁有一個Looper,當Looper準備好之后會讓線程進入死循環,如果內部的Message隊列不為空時,則會不停的從消息隊列頭部取出一條Message進行消費,直到隊列為空,Looper阻塞線程進入等待狀態。Message內部會記錄著發送消息的Handler,當被消費時就可以找到對應的Handler進行消息處理,最終形成閉環。

使用C++11實現Android系統的Handler機制

實現

下面嘗試使用C++11來實現Android系統Handler機制,該實現主要由AlHandlerThread、AlHandler、AlLooperManager、AlLooper、AlMessageQueue和AlMessage六個類組成。我們規定一個線程只能擁有一個AlLooper,因此需要一個AlLooperManager負責對所有線程的AlLooper對象進行管理,如果當前線程已經擁有了AlLooper對象,則直接使用當前線程的對象,保證AlLooper唯一。而AlMessageQueue則是一個支持線程阻塞和喚醒的消息隊列。AlHandlerThread則是一個封裝了std::thread和AlLooper的簡單線程實現,僅僅是為了方便使用AlLooper,與Android系統中的HandlerThread實現是一致的。

使用C++11實現Android系統的Handler機制

AlHandler

AlHandler提供兩個構造函數,第一個只有Callback參數,該構造函數會默認獲取當前線程的AlLooper,如果當前沒有AlLooper,則會拋出異常。第二個構造函數支持傳入一個AlLooper,該AlLooper對象將會從AlHandlerThread獲取。sendMessage函數負責把AlMessage轉發到AlLooper,值得注意的是,在發送到AlLooper之前會先給AlMessage的成員變量target賦值,也就是當前AlHandler對象的指針。dispatchMessage函數用于在AlLooper中消費消息。

class AlHandler {public: typedef function<void(AlMessage *msg)> Callback;public: AlHandler(Callback callback); AlHandler(AlLooper *looper, Callback callback); void sendMessage(AlMessage *msg) { _enqueueMessage(msg); } void dispatchMessage(AlMessage *msg) { if (callback) { callback(msg); } }private: void _enqueueMessage(AlMessage *msg) { if (this->looper) { msg->target = this; this->looper->sendMessage(msg); } }private: AlLooper *looper = nullptr; Callback callback = nullptr;};

AlLooperManager

AlLooperManager只有一個功能,那就是管理所有創建的AlLooper對象,所以它是一個單例,代碼雖然簡單,但卻很重要。由于操作系統會為每一個線程分配一個唯一的tid(Thread ID,Linux下可以使用pthread_self獲取到),所以我們可以通過tid的唯一性來管理所有線程創建的AlLooper對象。該類的create和get函數分別用于創建新的AlLooper對象,以及獲取緩存的對象。創建一個對象時首先需要檢查緩存中是否存在該線程對應的AlLooper,如果已經存在則應該避免重復創建,直接返回空指針即可。而get函數用于從緩存中獲取一個對象,如果緩存中沒有則返回空指針。remove用于銷毀一個AlLooper,一般會在線程銷毀時使用。這幾個函數都需要保證線程安全。

private: AlLooperManager() : Object() {} AlLooperManager(AlLooperManager &e) : Object() {} ~AlLooperManager() {} /** * 為當前線程創建Looper * @return 當前線程的Looper */ AlLooper *create(long tid) { std::lock_guard<std::mutex> guard(mtx); auto it = looperMap.find(tid); if (looperMap.end() == it) { auto *looper = new AlLooper(); looperMap[tid] = looper; return looper; } return nullptr; } /** * 獲取當前線程的Looper * @return 當前線程的Looper */ AlLooper *get(long tid) { std::lock_guard<std::mutex> guard(mtx); auto it = looperMap.find(tid); if (looperMap.end() == it) { return nullptr; } return it->second; } /** * 銷毀當前線程的Looper */ void remove(long tid) { std::lock_guard<std::mutex> guard(mtx); auto it = looperMap.find(tid); if (looperMap.end() != it) { looperMap.erase(it); auto *looper = it->second; delete looper; } }private: static AlLooperManager *instance; std::map<long, AlLooper *> looperMap; std::mutex mtx;};

AlLooper

AlLooper主要有prepare、myLooper和loop三個靜態函數。prepare用于為當前線程準備一個AlLooper,因為我們規定同一個線程只能擁有一個AlLooper對象,如果嘗試在一個線程重復調用該函數函數將引發異常。myLooper用于獲取當前線程的AlLooper,如果在該函數調用之前沒有調用過prepare將會獲得一個空指針。loop是AlLooper的核心函數,調用該函數后線程將進入死循環,AlLooper會依次從消息隊列頭部取出AlMessage進行消費。前面提到AlMessage有一個名為target的成員變量,這個變量是一個AlHandler對象,所以這里直接調用AlHandler::dispatchMessage函數把消息回傳,由AlHandler進行處理。sendMessage函數則用于在消息隊列尾部插入一條消息。

class AlLooper : public Object {public: /** * 為線程準備一個Looper,如果線程已經存在Looper,則報錯 */ static void prepare() { AlLooper *looper = AlLooperManager::getInstance()->create(Thread::currentThreadId()); assert(nullptr != looper); } /** * 獲取當前線程的Looper * @return 前線程的Looper */ static AlLooper *myLooper() { AlLooper *looper = AlLooperManager::getInstance()->get(Thread::currentThreadId()); assert(nullptr != looper); return looper; } static void exit(); /** * 循環消費消息 */ static void loop() { myLooper()->_loop(); } void _loop() { for (;;) { AlMessage *msg = queue.take(); if (msg) { if (msg->target) { msg->target->dispatchMessage(msg); } delete msg; } queue.pop(); } } void sendMessage(AlMessage *msg) { queue.offer(msg); }private: AlLooper(); AlLooper(AlLooper &e) : Object() {} ~AlLooper();private: AlMessageQueue queue;};

AlMessageQueue和AlMessage

AlMessage比較簡單,主要包含幾個public的成員變量,用于區分消息類型以及附帶一些信息。AlMessageQueue則是一個阻塞隊列,當嘗試從一個空隊列獲取AlMessage時將會造成線程阻塞,如果其它線程向空隊列新增一個AlMessage對象將會喚醒阻塞的線程。這是驅動消息循環消費的重要一環。

class AlMessage {public: int32_t what = 0; int32_t arg1 = 0; int64_t arg2 = 0; Object *obj = nullptr;}class AlMessageQueue : public Object {public: AlMessageQueue() { pthread_mutex_init(&mutex, nullptr); pthread_cond_init(&cond, nullptr); } virtual ~AlMessageQueue() { pthread_mutex_lock(&mutex); invalid = true; pthread_mutex_unlock(&mutex); clear(); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); } void offer(AlMessage *msg) { pthread_mutex_lock(&mutex); if (invalid) { pthread_mutex_unlock(&mutex); return; } queue.push_back(msg); pthread_cond_broadcast(&cond); pthread_mutex_unlock(&mutex); } AlMessage *take() { pthread_mutex_lock(&mutex); if (invalid) { pthread_mutex_unlock(&mutex); return nullptr; } if (size() <= 0) { if (0 != pthread_cond_wait(&cond, &mutex)) { pthread_mutex_unlock(&mutex); return nullptr; } } if (queue.empty()) { pthread_mutex_unlock(&mutex); return nullptr; } AlMessage *e = queue.front(); queue.pop_front(); pthread_mutex_unlock(&mutex); return e; } int size(); void clear();private: pthread_mutex_t mutex; pthread_cond_t cond; std::list<AlMessage *> queue; bool invalid = false;};

AlHandlerThread

AlLooper準備好后就可以在線程中使用了,這里我們把線程和AlLooper封裝到一起方便使用。AlHandlerThread會在內部開啟一個線程,該線程會調用run函數,在線程開始運行后依次調用AlLooper的prepare和loop函數即可進入消息消費流程,AlLooper::exit()用于在線程結束前銷毀AlLooper對象。

class AlHandlerThread {public: AlLooper *getLooper() { return mLooper; }private: void run() { AlLooper::prepare(); mLooper = AlLooper::myLooper(); AlLooper::loop(); AlLooper::exit(); }private: std::thread mThread = thread(&AlHandlerThread::run, this); AlLooper *mLooper = nullptr;};

最后我們創建一個AlHandler對象,并傳入一個從AlHandlerThread獲取的AlLooper對象和一個處理回調函數Callback,便可以讓Handler機制運行起來。由于AlLooper可以是任意一個線程的對象,所以便實現了跨線程的通訊。如果我們把AlMessage封裝成一個'Task',當我們要處理一個耗時任務時,把任務封裝成一個'Task'發送到Handler進行處理,通過該方法可以輕易實現線程的復用,而不需要重復申請銷毀線程。

mThread = AlHandlerThread::create(name);mHandler = new AlHandler(mThread->getLooper(), [this](AlMessage *msg) { /// Do something.});

結語

  以上便是Android系統Handler機制的介紹,以及使用C++11的實現。上面展示的是部分核心代碼,省略了很多,實際操作還需要處理很多問題,比如線程安全、線程的退出、AlLooper的銷毀等。文章源碼出自hwvc項目,感興趣的讀者可以閱讀完整的AlHandlerThread源碼實現。

hwvc項目:

https://github.com/imalimin/hwvc/tree/develop

AlHandlerThread源碼:

https://github.com/imalimin/hwvc/blob/develop/src/common/thread/AlHandlerThread.cpp

到此這篇關于使用C++11實現Android系統的Handler機制的文章就介紹到這了,更多相關C++11 Handler機制內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Android
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产亚洲精aa在线看| 亚洲人成亚洲精品| 欧美午夜网站| 国产精品videossex| 国产精品115| 国产在线观看www| 国产真实久久| 亚洲精品进入| 国产精品白丝一区二区三区| 91亚洲国产成人久久精品| 亚洲成人二区| 中文字幕一区二区三区在线视频| 国产日韩免费| 日韩在线中文| 亚洲精品高潮| 国产精品美女在线观看直播| 国产一区二区三区黄网站| 人人精品亚洲| 一区二区高清| 精品欠久久久中文字幕加勒比| 亚洲成人国产| 欧美一级久久| 激情久久久久久久| 欧美精品国产白浆久久久久| 涩涩av在线| 亚州精品视频| 中文在线а√天堂| 亚洲精品乱码| 欧美不卡高清一区二区三区| 中文一区一区三区免费在线观 | 国产精品一区三区在线观看| 日产精品一区二区| 蜜桃久久精品一区二区| 久久这里只有| 欧美日韩国产高清电影| 日本中文字幕视频一区| 中文字幕在线免费观看视频| 一区二区精彩视频| sm久久捆绑调教精品一区| 中文不卡在线| 老鸭窝一区二区久久精品| 亚洲深夜福利| 国产传媒在线观看| 亚洲va久久久噜噜噜久久| 成人av三级| 日韩精品高清不卡| 欧美一区二区三区激情视频| 免费视频一区二区三区在线观看| 国产亚洲午夜| 日韩成人三级| 日韩精品福利一区二区三区| 国产在线欧美| 高清久久精品| 久久精品av麻豆的观看方式| 国产精品普通话对白| 日韩伦理在线一区| 国产伦精品一区二区三区视频| 一区免费在线| 日韩免费福利视频| 美女av一区| 欧美日韩一区二区三区在线电影| 亚洲欧美日韩国产一区二区| 欧美日韩视频网站| 国产一区二区视频在线看| 午夜亚洲福利| 尹人成人综合网| 99久久婷婷| 日韩高清欧美| 成人精品久久| 久久亚洲精品中文字幕| 国产欧美日韩精品一区二区三区| 综合一区在线| 免费观看久久久4p| 亚洲尤物在线| 麻豆91精品| 亚洲综合日本| 亚洲欧美日韩视频二区| 狠狠色综合网| 国产精品毛片| 怡红院精品视频在线观看极品| 日韩精品免费一区二区在线观看 | 国产精品久久亚洲不卡| 日韩一二三区在线观看| 丝袜美腿亚洲色图| 亚洲一级在线| 国产一区二区精品| 亚洲综合不卡| 中文视频一区| 免费成人av在线播放| 亚洲免费激情| 日韩在线a电影| 中文字幕一区二区三区日韩精品| 国产精品社区| 一区在线观看| 丝袜美腿一区二区三区| 免费在线观看日韩欧美| 美国三级日本三级久久99| 免费在线看一区| 在线精品一区| 日韩精品一区二区三区中文字幕| 日韩和欧美一区二区| 97久久亚洲| 国产精品2区| 成人在线免费观看网站| 欧美片第1页| 狠狠色狠狠色综合日日tαg| 亚洲欧美日韩一区在线观看| 亚洲aa在线| 国产精品一区二区三区av麻| 美女尤物国产一区| 日韩精品诱惑一区?区三区| 亚洲午夜黄色| 亚洲理论在线| 久久wwww| 久久久久国产精品一区二区| 欧美成人综合| 亚洲人成精品久久久| 欧美欧美黄在线二区| 久久久久久色 | 国产精品欧美日韩一区| 精品五月天堂| 99视频精品全部免费在线视频| 99国产精品99久久久久久粉嫩| 综合日韩在线| 成人午夜网址| 亚洲欧美日韩国产一区| 欧美亚洲三级| 神马午夜在线视频| 久久国产88| 欧美精品不卡| 国产二区精品| 欧美影院精品| 日韩综合一区| 免播放器亚洲一区| 精品国产三区在线| av不卡在线| 久久69成人| 免费在线视频一区| 久久男人av| 国产亚洲网站| 精品久久影院| 蜜臀av一区二区在线免费观看| 欧美精品第一区| 国产精品视区| 成人一二三区| 蜜臀久久99精品久久久久久9 | 先锋影音国产一区| 麻豆视频观看网址久久| 免费精品国产的网站免费观看| 日韩激情一二三区| 久久香蕉国产| 麻豆久久久久久| 国产午夜精品一区二区三区欧美 | 亚洲综合五月| 久久久国产精品一区二区中文| 中文字幕日韩亚洲| 中文字幕在线官网| 日韩欧美激情| 欧美特黄一区| 黄毛片在线观看| 欧美亚洲一级| 日韩精品一级二级| 99精品电影| 精品一区二区三区的国产在线观看| 中文国产一区| 快播电影网址老女人久久| 国产欧美日韩精品一区二区免费| 黄色成人91| 日本欧美不卡| 麻豆高清免费国产一区| 欧美1区2区3区| 日本欧美国产| 国产精品欧美一区二区三区不卡| 日韩中文字幕麻豆| 美女毛片一区二区三区四区| 蜜桃久久久久| 欧美久久香蕉| 亚洲黄色在线| 欧美中文字幕一区二区| 国产成人精品免费视| 视频在线观看91| 欧美日韩激情| 日韩另类视频| 日韩欧美一区二区三区在线视频| 国产精品久久久久久模特| 免费视频最近日韩| 欧美日韩亚洲在线观看| 色一区二区三区四区| 国产精品亚洲综合色区韩国| 日本不卡一区二区| 免费日韩一区二区| 亚洲精华国产欧美| 免费精品国产的网站免费观看| 日产精品一区| 国产日韩电影| 视频二区不卡| 日韩电影二区| 久久久久99| 亚洲香蕉网站| 亚洲精品成人|