ios跨線程通知_iOS多線程開發(三)---Run Loop(一)

Run Loop

Run Loop就是一個事件處理的循環,用來不停的調動工作以及處理輸入事件。使用Run Loop的目的就是節省CPU效率,線程在有工作的時候忙于工作,而沒工作的時候處于休眠狀態。

一,Run Loop剖析

Structure of a Run Loop and its sources

上圖顯示了線程的輸入源

A,基于端口的輸入源(Port Sources)

B,自定義輸入源(Custom Sources)

C,Cocoa執行Selector的源("performSelector...方法" Sources)

D,定時源(Timer Sources )

線程針對上面不同的輸入源,有不同的處理機制

A,handlePort---處理基于端口的輸入源

B,customSrc---處理用戶自定義輸入源

C,mySelector---處理Selector的源

D,timerFired---處理定時源

注:線程除了處理輸入源,Run Loops也會生成關于Run Loop行為的通知(notification)。Run Loop觀察者(Run-Loop Observers)可以收到這些通知,并在線程上面使用他們來作額為的處理

===在新線程的Run Loop中注冊Observers:

---編寫一個帶有觀測者的線程加載程序

- (void)observerRunLoop

{

// 建立自動釋放池

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// 獲得當前thread的Run loop

NSRunLoop *myRunLoop = [NSRunLoop currentRunLoop];

// 設置Run Loop observer的運行環境

CFRunLoopObserverContext context = {0, self, NULL, NULL, NULL};

// 創建Run loop observer對象

// 第一個參數用于分配該observer對象的內存

//?第二個參數用以設置該observer所要關注的的事件,詳見回調函數myRunLoopObserver中注釋

//?第三個參數用于標識該observer是在第一次進入run loop時執行還是每次進入run loop處理時均執行

//?第四個參數用于設置該observer的優先級

//?第五個參數用于設置該observer的回調函數

//?第六個參數用于設置該observer的運行環境

CFRunLoopObserverRef observer = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, &myRunLoopObserver, &context);

if(observer)

{

// 將Cocoa的NSRunLoop類型轉換程Core Foundation的CFRunLoopRef類型

CFRunLoopRef ? = [myRunLoop getCFRunLoop];

// 將新建的observer加入到當前的thread的run loop

CFRunLoopAddObserver(cfRunLoop, observer, kCFRunLoopDefaultMode);

}

// Creates and returns a new NSTimer object and schedules it on the current run loop in the default mode

[NSTimer scheduledTimerWithTImeInterval:0.1 target:self selector:@selector(doFireTimer:) userInfor:nil repeats:YES];

NSInteger = loopCount = 10;

do

{

// 啟動當前thread的run loop直到所指定的時間到達,在run loop運行時,run loop會處理所有來自與該run loop聯系的input sources的數據

// 對于本例與當前run loop聯系的input source只有Timer類型的source

// 該Timer每隔0.1秒發送觸發時間給run loop,run loop檢測到該事件時會調用相應的處理方法(doFireTimer:)

// 由于在run loop添加了observer,且設置observer對所有的run loop行為感興趣

// 當調用runUntilDate方法時,observer檢測到run loop啟動并進入循環,observer會調用其回調函數,第二個參數所傳遞的行為時kCFRunLoopEntry

// observer檢測到run loop的其他行為并調用回調函數的操作與上面的描述相類似

[myRunLoop runUntilDate:[NSDate dateWithTimeIntervalSiceNow:1.0]];

// 當run loop的運行時間到達時,會退出當前的run loop,observer同樣會檢測到run loop的退出行為,并調用其回調函數,第二個參數傳遞的行為是kCFRunLoopExit.

--loopCount;

}while(loopCount);

//?釋放自動釋放池

[pool release];

}

===observer的回調函數:

void myRunLoopObserver(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)

{

switch(activity)

{

// The entrance of run loop, before entering the event processing loop.

//?This activity occurs once for each call to CFRunLoopRun / CFRunLoopRunInMode

case kCFRunLoopEntry:

NSLog(@"run loop entry");

break;

// Inside the event processing loop before any timers are processed

case kCFRunLoopBeforeTimers:

NSLog(@"run loop before timers");

break;

// Inside the event processing loop before any sources are processed

case kCFRunLoopBeforeSources:

NSLog(@"run loop before sources");

break;

// Inside the event processing loop before the run loop sleeps, waiting for a source or timer to fire

// This activity does not occur if CFRunLoopRunInMode is called with a timeout of o seconds

// It also does not occur in a particular iteration of the event processing loop if a version 0 source fires

case kCFRunLoopBeforeWaiting:

NSLog(@"run loop before waiting");

break;

//?Inside the event processing loop after the run loop wakes up, but before processing the event that woke it up

//?This activity occurs only if the run loop did in fact go to sleep during the current loop

case kCFRunLoopAfterWaiting:

NSLog(@"run loop after waiting");

break;

// The exit of the run loop, after exiting the event processing loop

// This activity occurs once for each call to CFRunLoopRun and CFRunLoopRunInMode

case kCFRunLoopExit:

NSLog(@"run loop exit");

break;

/*

A combination of all the preceding stages

case kCFRunLoopAllActivities:

break;

*/

default:

break;

}

}

1,Run Loop模式---是所有要監測的輸入源和定時源以及要通知的run loop注冊觀察者的集合。在run loop運行過程中,只有和模式相關的源才會被監測并允許他們傳遞事件消息。相反,沒有被添加的輸入源將會被過濾。

可以自定自己的Run Loop模式,但是每個模式必須有一個或者多個輸入源,定時源或者run loop的觀察者,否則,run loop直接退出,Run Loop模式將沒有意義。

另,模式區分基于事件的源而非事件的種類。例如,不能使用模式只選擇處理鼠標按下或者鍵盤事件。可以使用模式監聽端口,而暫停定時器或者改變其他源或者當前模式下處于監聽狀態run loop觀測著。

表1-1列出了cocoa和Core Foundation預先定義的模式。

2,Run Loop的輸入源

A,基于端口的輸入源

通過內置的端口相關的對象和函數,創建配置基于端口的輸入源。相關的端口函數---CFMachPort/CFMessagePortRef/CFSocketRf

B,自定義輸入源

自定義輸入源使用CFRunLoopSourceRef對象創建,它需要自定義自己的行為和消息傳遞機制

C,Cocoa執行Selector的源

和基于端口的源一樣,執行Selector的請求會在目標線程上序列化,減緩在線程上允許許多各方法容易引起的同步問題。兩者區別:一個Selector執行完成后會自動從Run Loop上移除。

Table:Performing selectors on other threads

MethodsDescription

Performs the specified selector on the

application’s main thread during that

thread’s next run loop cycle. These

methods give you the option of blocking

the current thread until the selector is

performed.

Performs the specified selector on any

thread for which you have an?NSThread

object. These methods give you the

option of blocking the current thread

until the selector is performed.

Performs the specified selector on the

current thread during the next run loop

cycle and after an optional delay period.

Because it waits until the next run loop

cycle to perform the selector, these

methods provide an automatic mini

delay from the currently executing code.

Multiple queued selectors are performed

one after another in the order they were

queued.

D,定時源

在預設的時間點同步方式傳遞消息,定時器是線程通知自己做某事的一種方法。

E,Run Loop觀察者

源是合適的同步/異步事件發生時觸發。觀察者則是在Run Loop本身運行的特定時候觸發。觀察者觸發的相關事件(參考上面紅色程序里面的函數:myRunLoopObserves(...))

1)Run Loop入口

2)Run Loop何時處理一個定時器

3)Run Loop何時處理一個輸入源

4)Run Loop何時進入休眠狀態

5)Run Loop何時被喚醒,但在喚醒之前要處理的事件

6)Run Loop終止

注:1,觀察者通過CFRunLoopObserverRef對象創建的

2,觀察者會在相應事件發生之前傳遞消息,所以通知的時間和事件實際發生的時間之間肯定有誤差

F,Run Loop 的事件隊列--包括觀察者的事件隊列

1)通知觀察者Run Loop已經啟動

2)通知觀察者任何即將要開始的定時器

3)通知觀察者任何即將啟動的非基于端口的輸入源

4)啟動任何準備好的非基于端口的源

5)如果基于端口的源準備好了并處于等待狀態,立即啟動;并進入步驟9

6)通知觀察者線程進入休眠

7)將線程置于休眠直到下面任一事件發生

A)某一事件到達基于端口的源

B)定時器啟動

C)Run Loop設置的時間已經超時

D)Run Loop被顯式喚醒

8)通知觀察者線程被喚醒

9)處理未處理的事件

A)如果用戶定義的定時器啟動,處理定時器事件并重啟Run Loop,進入步驟2

B)如果輸入源啟動,傳遞相應消息

C)如果Run Loop被顯式喚醒而且時間還沒有超時,重啟Run Loop,進入步驟2

10)通知觀察者Run Loop結束

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/260013.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/260013.shtml
英文地址,請注明出處:http://en.pswp.cn/news/260013.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

android播放flv,Android:從url播放flv視頻流

我目前有一個應用程序,它可以記錄視頻并將其上傳到我的服務器。在上傳視頻之后,應用程序會獲得一個響應,該響應包含指向該文件的flv流的URL。Android:從url播放flv視頻流當我嘗試在android默認視頻播放器(視頻)中打開流時什么也沒…

1.關于瀏覽器

一、認識主流瀏覽器 Chrome谷歌瀏覽器Safari蘋果瀏覽器Firefox火狐瀏覽器Opera歐朋瀏覽器 二、瀏覽器內核是什么? 三、五大瀏覽器,四大內核 四、前端做網頁開發用什么瀏覽器? Chrome谷歌瀏覽器。

About me [my way]

就要除夕了。假日的到來,心情瞬間就閑適了下來。早早上了床,看看電腦還有30%的電,想到一些事情,順帶紀錄一下吧。 今年堅持上班到了除夕的前一天,爸媽來工作的城市陪我過年了。感謝他們。前幾天就已經看帖子有說仍在上…

明天要中秋節了,先來到簡單“類”的題目

2-1 Point類的定義 Time Limit: 1000MS Memory limit: 65536K 題目描述 通過本題目的練習可以掌握類與對象的定義; 設計一個點類Time,它具有私有數據成員x(橫坐標)、y(縱坐標);公有成員函數:SetPoint(int,int)用于設置點對象的值&…

實時數據交換平臺 - BottledWater-pg with confluent

標簽 PostgreSQL , Bottled Water , Kafka , Confluent , IoT 背景 想必大家都在圖書館借過書,小時候有好看的書也會在小伙伴之間傳閱。 借書和數據泵有點類似,一份數據通過數據泵實時的分享給訂閱者。 例如在IoT的場景中,有流式分析的需求&a…

科技鴻蒙系統一千章,第一千六百零七章 鴻蒙紫氣,成圣之機 (上)

文學迷 > 玄幻魔法 > 天命神相 > 第一千六百零七章 鴻蒙紫氣,成圣之機 (上)第一千六百零七章 鴻蒙紫氣,成圣之機功德金身只要達到了八十一重天,大圓滿的境界,實力堪混元大羅級別的圣人,這聽起來確實是一件吊炸…

js reduce實現中間件_js數組高階方法reduce經典用法代碼分享

以下是個人在工作中收藏總結的一些關于javascript數組方法reduce的相關代碼片段,后續遇到其他使用這個函數的場景,將會陸續添加,這里作為備忘。javascript數組那么多方法,為什么我要單挑reduce方法,一個原因是我對這個…

struts2的s:iterator 標簽 詳解

struts2的s:iterator 可以遍歷 數據棧里面的任何數組,集合等等 以下幾個簡單的demo:s:iterator 標簽有3個屬性: value:被迭代的集合 id :指定集合里面的元素的id status 迭代元素的索引1:jsp…

Protocol Buffers的應用

1. Protocol Buffers的介紹 Protocol buffers are Google’s language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then …

編程提高:一天一道編程題

1.文本操作 逆轉字符串——輸入一個字符串,將其逆轉并輸出。 拉丁豬文字游戲——這是一個英語語言游戲。基本規則是將一個英語單詞的第一個輔音音素的字母移動到詞尾并且加上后綴-ay(譬如“banana”會變成“anana-bay”)。可以在維基百科上了…

android自驗簽名證書,沒有以前的互聯網連接,無法驗證Android自簽名證書

使用SSL基礎架構:我們有一個有效的客戶端/服務器設置,其中Android版本4.2和4.4的手機充當客戶端,必須通過其自簽名SSL證書驗證服務器.問題:只要設備在嘗試連接之前至少有一次互聯網訪問權限,服務器證書驗證就會起作用.但是,如果執行恢復出廠設置且設備直…

asp.net緩存(二)

ASP.NET頁面局部緩存 有時緩存整個頁面是不現實的,因為頁的某些部分可能在每次請求時都需要變化。在這些情況下,只能緩存頁的一部分。顧名思義,頁面部分緩存是將頁面部分內容保存在內存中以便響應用戶請求,而頁面其他部分內容則為…

學習C# - Hello,World!

第一天學C#,開始學著寫一些學習筆記,看了一下傳智播客的視頻,按照傳智播客的教學順序,開始學習。 class Program{static void Main(string[] args){Console.WriteLine("Hello World!");//自動添加回車換行Console.Write("Hell…

android獲取button寬度,android – 如何獲得Button的高度和寬度

我創建了一系列按鈕.現在我想找到按鈕的高度和寬度,為此我使用了getWidth()和getHeight().但問題是它總是返回0.為什么會發生這種情況?我發送了我的代碼,請檢查是否有任何問題.int x,y;LinearLayout layoutVertical (LinearLayout) findViewById(R.id.liVLayout);L…

java執行sql列名無效_嵌套異常是java.sql.SQLException:無效的列名ORACLE

我嘗試在Java中使用JdbcTemplate執行以下oracle查詢:select RESOURCE_IDfrom REPRO_PRINTING_JOBwhere (USER_ID? and PRINTING_CENTER_ID?)group by RESOURCE_IDunion allselect RESOURCE_IDfrom REPRO_PRINTING_JOB_OLDwhere (USER_ID? and PRINTING_CENTER_ID…

(七)Maven使用的最佳實踐

這里說一下在使用Maven過程中不是必須的,但十分有用的幾個實踐,關鍵時刻或許能解決您的問題。 1.設置MAVEN_OPTS環境變量 通常需要設置MAVEN_OPTS的值為-Xms128m -Xmx512m,因為Java默認的最大可用內存往往不能夠滿足Maven運行的需要&#xff…

android beam傳輸速率,無線網絡的速率為何不能達到最大值

1、無線速率可以達到最大值,只是發送速率和傳輸流量是兩個概念,通俗點講,無線的發送速率是把信號以指定速率發出去(信號好的時候以高速率發,信號差的時候以低速率發)。傳輸流量是指單位時間內傳輸的數據量,大部分用戶關…

【SMTP 補錄 Apache服務】

【補錄,續】1.【配置空殼郵件接受】【mta】【前置:在/etc/named.rfc1912.zones 添加一個可以接受郵件的域hxl.org(與你數據庫中寫的向對應),這個域的所在ip就是你機子的,因為要從你的機子轉發】 【配置該機的vim/etc/…

image打開rgb16 qt_QT中顯示圖像數據

一般圖像數據都是以RGBRGBRGB……字節流的方式(解碼完成后的原始圖像流),我說成字節流,那就表明R,G,B的值各占一個字節,在編程時表示的就是unsigned char * data。我們先來看一下QT中的QImage對象。在加載data數據前&a…

開啟chrome默認支持ipv6

在快捷方式后面的屬性后面輸入 --enable-ipv6 以下為轉載: [轉載]chrome開啟或關閉IPV6方法 (2012-05-27 17:54:06) 轉載▼ 標簽: 轉載 分類: 技術 原文地址:chrome開啟或關閉IPV6方法作者:余鯤濤 chrome和firefox都是…