久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

iOS多線程之NSRunloop

 quasiceo 2015-04-18

iOS多線程之NSRunloop

時(shí)間 2014-03-15 15:49:25 CSDN博客 原文  http://blog.csdn.net/joywii/article/details/21286659

1.簡介

Runloop是與線程有關(guān)的基礎(chǔ)框架的一部分,,是用來規(guī)劃事件處理的,,當(dāng)有任務(wù)的時(shí)候Runloop會(huì)讓線程處理任務(wù),當(dāng)沒有任務(wù)的時(shí)候Runloop會(huì)讓線程處于休眠狀態(tài),。
Runloop的管理不完全是自動(dòng)的,,我們必須在合適的時(shí)候開啟Runloop和處理到達(dá)的事件,Cocoa和Core Foundation都提供了Runloop對(duì)象來配置和管理線程的Runloop,。我們的應(yīng)用程序不需要顯示的創(chuàng)建這些對(duì)象,,包括應(yīng)用主線程在內(nèi)的每一個(gè)線程都有一個(gè)相關(guān)的Runloop對(duì)象。而且只有第二線程是需要顯示地運(yùn)行Runloop,,主線程是不需要的,,APP把主線程Runloop的配置和運(yùn)行作為了應(yīng)用程序啟動(dòng)的一部分。
操作Runloop的兩個(gè)接口: 1. NSRunLoop Class Reference 2. CFRunLoop Reference

2.Runloop解析

Runloop的功能就像他的名字聽起來一樣,,使線程進(jìn)入一個(gè)循環(huán),,當(dāng)事件到達(dá)的時(shí)候調(diào)用事件處理方法。我們要自己提供實(shí)現(xiàn)Runloop實(shí)際循環(huán)運(yùn)行的控制語句,,話句話說就是我們要提供 while 或者 for 來驅(qū)動(dòng)Runloop,。在循環(huán)內(nèi)部我們運(yùn)行Runloop,當(dāng)事件到達(dá)的時(shí)候調(diào)用事件處理器,。
Runloop接收來自兩種源的事件,, Input sources 異步的分發(fā)通常是來自于同一個(gè)應(yīng)用內(nèi)的另一個(gè)線程的消息事件。 Timer sources 同步的分發(fā)在設(shè)定好的時(shí)間發(fā)生或者循環(huán)間斷地發(fā)生的事件,。這兩種事件源都是使用應(yīng)用指定的事件處理方法來處理到達(dá)的事件,。

下面的圖顯示了Runloop和事件源的概念結(jié)構(gòu)。 Input sources 異步的分發(fā)事件到響應(yīng)的處理器,,然后引起runUntilDate:(由線程相關(guān)的Runloop對(duì)象調(diào)用)方法退出,。 Timer sources 同步分發(fā)事件到相應(yīng)的處理器但是不會(huì)引起Runloop退出,。


除了處理輸入源的事件,Runloop也會(huì)生成Runloop行為的通知,。注冊(cè)Runloop的觀察者可以收到這些消息,,然后在線程內(nèi)用他們做一些額外的處理。我們只能使用Core Foundation接口來注冊(cè)線程的Runloop觀察者,。

2.1 Runloop運(yùn)行模式

一種Runloop運(yùn)行模式就是一個(gè)要監(jiān)控的Input和Timer事件源的集合或者是一個(gè)要通知的Runloop觀察者的集合,。每次運(yùn)行Runloop,都要指定一個(gè)運(yùn)行模式(顯示地或者隱式地),。在Runloop的運(yùn)行期間,,只有和當(dāng)前運(yùn)行模式相關(guān)的源才能被監(jiān)控和允許發(fā)送事件。相似的,,只有和當(dāng)前運(yùn)行模式相關(guān)的觀察者才會(huì)被通知Runloop的行為,。和其他模式相關(guān)的源會(huì)保留新的事件直到Runloop運(yùn)行在了合適的模式才會(huì)分發(fā)。

在我們的代碼中,,我們可以通過字符串來標(biāo)識(shí)模式,。Cocoa和Core Foundation定義了一個(gè)默認(rèn)模式和幾個(gè)普通的有用的模式,這些模式都是用字符串來標(biāo)識(shí)的,。我們可以用一個(gè)字符串當(dāng)做名字來自定義一個(gè)模式,,雖然我們自定義模式的名字是隨意的,但是模式的內(nèi)容不是隨意的,,在我們自己創(chuàng)建的要用的模式中至少要添加一個(gè) Input源 ,、 Timer源 或者 Runloop觀察者

在Runloop的特殊階段我們可是使用運(yùn)行模式來過濾我們不想要的源的事件,,大多數(shù)的情況下,,Runloop都運(yùn)行在系統(tǒng)提供的默認(rèn)模式下,然而Model Panel可能運(yùn)行在“模式”模式,,當(dāng)運(yùn)行在這個(gè)模式期間,,只有和這個(gè)模式相關(guān)的事件源才會(huì)發(fā)送事件到我們的線程。對(duì)于第二線程來說,,我們通常使用自定義模式來阻止低優(yōu)先級(jí)的事件源在其他關(guān)鍵處理的時(shí)間內(nèi)發(fā)送事件,。

注意:運(yùn)行模式不是根據(jù)事件類型劃分的,而是根據(jù)事件源劃分的,。我們不能通過模式來匹配鼠標(biāo)按下事件或者鍵盤事件,,但是我們可以用運(yùn)行模式來監(jiān)聽一組不同的Port,、暫時(shí)掛起Timers或者改變當(dāng)前被監(jiān)控的事件源和Runloop觀察者,。

下面列舉了一些Cocoa和Core Foundation定義的標(biāo)準(zhǔn)模式:

  • NSDefaultRunLoopMode:默認(rèn)的運(yùn)行模式,用于大部分操作,,除了NSConnection對(duì)象事件,。
  • NSConnectionReplyMode:用來監(jiān)控NSConnection對(duì)象的回復(fù)的,,很少能夠用到。
  • NSModalPanelRunLoopMode:用于標(biāo)明和Mode Panel相關(guān)的事件,。
  • NSEventTrackingRunLoopMode:用于跟蹤觸摸事件觸發(fā)的模式(例如UIScrollView上下滾動(dòng)),。
  • NSRunLoopCommonModes:是一個(gè)模式集合,當(dāng)綁定一個(gè)事件源到這個(gè)模式集合的時(shí)候就相當(dāng)于綁定到了集合內(nèi)的每一個(gè)模式,。Cocoa應(yīng)用默認(rèn)包含Default,、Panel、Event Tracking模式,,Core Foundation只包含Default模式,,我們可以通過CFRunLoopAddCommonMode添加模式。

2.2 Input Sources

Input Sources異步地分發(fā)事件到線程,。大概有兩種類型的Input Sources,,Port-based類型的輸入源監(jiān)控著應(yīng)用的Mach端口,自定義的輸入源監(jiān)控著自定義的事件源,。NSRunloop不關(guān)心輸入源的類型,。兩種輸入源唯一的不同是輸入源的觸發(fā)方式,Port-based輸入源是由系統(tǒng)內(nèi)核觸發(fā)的,,而自定義的輸入源要我們自己觸發(fā),。創(chuàng)建輸入源的時(shí)候我們就給給輸入源添加指定的模式。下面是一些輸入源:

2.2.1 Port-Based Sources

Cocoa和Core Foundation提供了類和接口用來創(chuàng)建Port-Based源,,Cocoa只要?jiǎng)?chuàng)建NSPort對(duì)象,,并添加到NSRunloop中就可以啦,NSPort負(fù)責(zé)輸入源的創(chuàng)建和配置,。Core Foundation需要手動(dòng)的常見port和輸入源,。

2.2.2 Custom Input Sources

我們要用到 CFRunLoopSourceRef 函數(shù)創(chuàng)建輸入源,并定義幾個(gè)回調(diào)函數(shù)用于配置輸入源,、處理事件和刪除輸入源,。事件的觸發(fā)機(jī)制要我們自己定義。

2.2.3 Cocoa Perform Selector Sources

Cocoa定義了可以在任何線程上執(zhí)行方法的事件源,,在想要執(zhí)行的線程上執(zhí)行方法是順序執(zhí)行的,,避免了多個(gè)方法在線程上執(zhí)行的同步問題。Perform Selector Sources在方法執(zhí)行完之后就會(huì)自己從NSRunloop中刪除,。

Perform Selector Sources要求目標(biāo)線程的NSRunloop必須是運(yùn)行的,,主線程默認(rèn)是運(yùn)行的。NSRunloop在一次迭代過程中會(huì)處理所有的Perform Selector調(diào)用,,而不是一次迭代處理一個(gè)Perform Selector調(diào)用,。NSObject中定義的Perform Selector方法如下

  • performSelectorOnMainThread:withObject:waitUntilDone:
  • performSelectorOnMainThread:withObject:waitUntilDone:modes:
  • performSelector:onThread:withObject:waitUntilDone:
  • performSelector:onThread:withObject:waitUntilDone:modes:
  • performSelector:withObject:afterDelay:
  • performSelector:withObject:afterDelay:inModes:
  • cancelPreviousPerformRequestsWithTarget:
  • cancelPreviousPerformRequestsWithTarget:selector:object:
延遲執(zhí)行是在NSRunloop的 下一次迭代 中過了指定的延遲事件才執(zhí)行。取消操作是針對(duì)延遲執(zhí)行方法的,。

2.3 Timer Sources

Timer Sources同步地在將來的一個(gè)確定的時(shí)間分發(fā)事件到我們的線程,。Timers可以讓線程通知自己去處理一些事情,。Timers不是一個(gè) 實(shí)時(shí)的機(jī)制 ,當(dāng)Timers觸發(fā)的時(shí)候NSrunloop剛好正在執(zhí)行處理函數(shù),Timers會(huì)等待NSRunloop調(diào)用自己的處理函數(shù),。

Timers可以創(chuàng)建一次性的和重復(fù)性的事件,,當(dāng)創(chuàng)建重復(fù)性的事件的時(shí)候,Timers只會(huì)根據(jù)規(guī)劃好的觸發(fā)時(shí)間來重新規(guī)劃觸發(fā)時(shí)間,,而不是根據(jù)確切的觸發(fā)時(shí)間,。而且由于延遲觸發(fā)丟失了幾次觸發(fā)的話,Timers只會(huì)補(bǔ)充一次觸發(fā),。

2.4 NSRunloop觀察者

不像是事件源一樣在事件觸發(fā)的時(shí)候執(zhí)行處理函數(shù),。NSRunloop觀察者是在NSRunloop幾個(gè)執(zhí)行的特定的點(diǎn)觸發(fā)。NSRunloop可以觀察的幾個(gè)事件是:

  • 進(jìn)入NSRunloop
  • NSRunloop將要處理Timer事件
  • NSRunloop將要處理Input事件
  • NSRunloop將要進(jìn)入睡眠
  • NSRunloop被喚醒,,但是是在處理事件之前
  • 退出NSRunloop

創(chuàng)建觀察者的方法是 CFRunLoopObserverRef ,,我們可以通過Core Foundation方法添加到指定的NSRunloop。觀察者也可以創(chuàng)建一次性的和重復(fù)性的,。一次性的觀察者觸發(fā)之后就會(huì)從NSRunloop中刪除,。

2.5 NSRunloop事件順序

NSRunloop所有處理事件和通知觀察者的順序如下:

  1. 通知觀察者NSRunloop進(jìn)入
  2. 如果有Timer即將觸發(fā)時(shí),通知觀察者
  3. 如果有非Port的Input Sourc即將e觸發(fā)時(shí),,通知觀察者
  4. 觸發(fā)非Port的Input Source事件源
  5. 如果基于Port的Input Source事件源即將觸發(fā)時(shí),,立即處理該事件,跳轉(zhuǎn)到步驟9
  6. 通知觀察者當(dāng)前線程將進(jìn)入休眠狀態(tài)
  7. 將線程進(jìn)入休眠狀態(tài)直到有以下事件發(fā)生:基于Port的Input Source被觸發(fā),、Timer被觸發(fā),、Run Loop運(yùn)行時(shí)間到了過期時(shí)間、Run Loop被喚起
  8. 通知觀察者線程將要被喚醒
  9. 處理被觸發(fā)的事件:如果是用戶自定義的Timer,,處理Timer事件后重新啟動(dòng)Run Loop進(jìn)入步驟2,、如果線程被喚醒又沒有到過期時(shí)間,則進(jìn)入步驟2,、如果是其他Input Source事件源有事件發(fā)生,,直接處理這個(gè)事件
  10. 到達(dá)此步驟說明Run Loop運(yùn)行時(shí)間到期,或者是非Timer的Input Source事件被處理后,,Run Loop將要退出,,退出前通知觀察者線程已退出

3.什么時(shí)候使用NSRunloop

由于主線程的NSRunloop默認(rèn)自動(dòng)運(yùn)行,所以只有第二線程才需要我們自己運(yùn)行NSRunloop,。并不是所有使用線程的情況都要運(yùn)行NSRunloop,,下面一些情況你需要運(yùn)行NSRunloop:

  • 需要使用Port或者自定義Input Source與其他線程進(jìn)行通訊。
  • 需要在線程中使用Timer,。
  • 需要在線程上使用performSelector*****方法,。
  • 需要讓線程執(zhí)行周期性的工作。
  • NSURLConnection在子線程中發(fā)起異步請(qǐng)求,。

4.補(bǔ)充

4.1 線程安全性

基于Cocoa的接口不是線程安全的,,基于Core Foundation的接口是線程安全的。

4.2 自定義輸入源的原理圖


5.NSRunloop的使用

具體關(guān)于NSRunloop中NSTimer,、Runloop觀察者等運(yùn)行模式的使用參見 hrchen的ExamplesForBlog 例子,。由于NSPortMessage是私有接口,所以沒有實(shí)例,。

6.參考鏈接

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多