色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

您好,歡迎來(lái)電子發(fā)燒友網(wǎng)! ,新用戶?[免費(fèi)注冊(cè)]

您的位置:電子發(fā)燒友網(wǎng)>源碼下載>數(shù)值算法/人工智能>

再讀蘋果線程配置與Run Loop

大小:0.6 MB 人氣: 2017-10-12 需要積分:1
 本文為再讀蘋果《Threading Programming Guide》筆記第二篇,作者付宇軒表示:如今關(guān)于iOS多線程的文章層出不窮,但我覺(jué)得若想更好的領(lǐng)會(huì)各個(gè)實(shí)踐者的文章,應(yīng)該先仔細(xì)讀讀官方的相關(guān)文檔,打好基礎(chǔ),定會(huì)有更好的效果。
  文章中有對(duì)官方文檔的翻譯,也有自己的理解,官方文檔中代碼片段的示例在這篇文章中都進(jìn)行了完整的重寫,還有一些文檔中沒(méi)有的代碼示例,并且都使用Swift完成,給大家一些Objective-C與Swift轉(zhuǎn)換的參考。
  系列閱讀
  初識(shí)線程線程配置與Run Loop
  線程屬性配置
  線程也是具有若干屬性的,自然一些屬性也是可配置的,在啟動(dòng)線程之前我們可以對(duì)其進(jìn)行配置,比如線程占用的內(nèi)存空間大小、線程持久層中的數(shù)據(jù)、設(shè)置線程類型、優(yōu)先級(jí)等。
  配置線程的棧空間大小
  在前文中提到過(guò)線程對(duì)內(nèi)存空間的消耗,其中一部分就是線程棧,我們可以對(duì)線程棧的大小進(jìn)行配置:
  Cocoa框架:在OS X v10.5之后的版本和iOS2.0之后的版本中,我們可以通過(guò)修改NSThread類的stackSize屬性,改變二級(jí)線程的線程棧大小,不過(guò)這里要注意的是該屬性的單位是字節(jié),并且設(shè)置的大小必須得是4KB的倍數(shù)。POSIX API:通過(guò)pthread_attr_- setstacksize函數(shù)給線程屬性pthread_attr_t結(jié)構(gòu)體設(shè)置線程棧大小,然后在使用pthread_create函數(shù)創(chuàng)建線程時(shí)將線程屬性傳入即可。
  注意:在使用Cocoa框架的前提下修改線程棧時(shí),不能使用NSThread的detachNewThreadSelector: toTarget:withObject:方法,因?yàn)樯衔闹姓f(shuō)過(guò),該方法先創(chuàng)建線程,即刻便啟動(dòng)了線程,所以根本沒(méi)有機(jī)會(huì)修改線程屬性。
  配置線程存儲(chǔ)字典 配置線程類型 設(shè)置線程優(yōu)先級(jí)
  注意:設(shè)置線程的優(yōu)先級(jí)時(shí)可以在線程運(yùn)行時(shí)設(shè)置。
  線程執(zhí)行的任務(wù)
  Autorelease Pool
  - (void)myThreadMainRoutine { NSAutoreleasePool*pool = [[NSAutoreleasePoolalloc] init]; // 頂層自動(dòng)釋放池// 線程執(zhí)行任務(wù)的邏輯代碼[pool release]; }
  - (void)myThreadMainRoutine { @autoreleasepool{ // 線程執(zhí)行任務(wù)的邏輯代碼} }
  intmain(intargc, char* argv[]) { @autoreleasepool{ returnUIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } }
  func performInBackground(){ autoreleasepool({ // 線程執(zhí)行任務(wù)的邏輯代碼 print(“I am a event, perform in Background Thread.”)})}
  func performInBackground(){ autoreleasepool{ // 線程執(zhí)行任務(wù)的邏輯代碼print(“I am a event, perform in Background Thread.”)} }
  設(shè)置異常處理 創(chuàng)建Runloop
  簡(jiǎn)單的來(lái)說(shuō),RunLoop用于管理和監(jiān)聽(tīng)異步添加到線程中的事件,當(dāng)有事件輸入時(shí),系統(tǒng)喚醒線程并將事件分派給RunLoop,當(dāng)沒(méi)有需要處理的事件時(shí),RunLoop會(huì)讓線程進(jìn)入休眠狀態(tài)。這樣就能讓線程常駐在進(jìn)程中,而不會(huì)過(guò)多的消耗系統(tǒng)資源,達(dá)到有事做事,沒(méi)事睡覺(jué)的效果。
  終止線程
  Run Loop
  注:Core Foundation框架是一組C語(yǔ)言接口,它們?yōu)閕OS應(yīng)用程序提供基本數(shù)據(jù)管理和服務(wù)功能,比如線程和Run Loop、端口、Socket、時(shí)間日期等。
  注:在二級(jí)線程中獲取Run Loop有兩種方式,通過(guò)NSRunloop的類方法currentRunLoop獲取Run Loop對(duì)象(NSRunLoop),或者通過(guò)Core Foundation框架中的CFRunLoopGetCurrent()函數(shù)獲取當(dāng)前線程的Run Loop對(duì)象(CFRunLoop)。NSRunLoop是CFRunLoop的上層封裝。
  letnsrunloop = NSRunLoop.currentRunLoop() letcfrunloop = CFRunLoopGetCurrent()
  Run Loop的事件來(lái)源 Run Loop的觀察者
  Run Loop準(zhǔn)備開(kāi)始運(yùn)行時(shí)。當(dāng)Run Loop準(zhǔn)備要執(zhí)行一個(gè)Timer Source事件時(shí)。當(dāng)Run Loop準(zhǔn)備要執(zhí)行一個(gè)Input Source事件時(shí)。當(dāng)Run Loop準(zhǔn)備休眠時(shí)。當(dāng)Run Loop被進(jìn)入的事件消息喚醒并且還沒(méi)有開(kāi)始讓處理器執(zhí)行事件消息時(shí)。退出Run Loop時(shí)。
  Run Loop的觀察者在NSRunloop中沒(méi)有提供相關(guān)接口,所以我們需要通過(guò)Core Foundation框架使用它,可以通過(guò)CFRunLoopObserverCreate方法創(chuàng)建Run Loop的觀察者,類型為CFRunLoopObserverRef,它其實(shí)是CFRunLoopObserver的重定義名稱。上述的那些可以被監(jiān)聽(tīng)的運(yùn)行狀態(tài)被封裝在了CFRunLoopActivity結(jié)構(gòu)體中,對(duì)應(yīng)關(guān)系如下:
  CFRunLoopActivity.EntryCFRunLoopActivity.BeforeTimersCFRunLoopActivity.BeforeSourcesCFRunLoopActivity.BeforeWaitingCFRunLoopActivity.AfterWaitingCFRunLoopActivity.Exit
  Run Loop的觀察者和Timer事件類似,可以只使用一次,也可以重復(fù)使用,在創(chuàng)建觀察者時(shí)可以設(shè)置。如果只使用一次,那么當(dāng)監(jiān)聽(tīng)到對(duì)應(yīng)的狀態(tài)后會(huì)自行移除,如果是重復(fù)使用的,那么會(huì)留在Run Loop中多次監(jiān)聽(tīng)Run Loop相同的運(yùn)行狀態(tài)。
  Run Loop Modes
  Run Loop Modes可以稱之為Run Loop模式,這個(gè)模式可以理解為對(duì)Run Loop各種設(shè)置項(xiàng)的不同組合,舉個(gè)例子,iPhone手機(jī)運(yùn)行的iOS有很多系統(tǒng)設(shè)置項(xiàng),假設(shè)白天我打開(kāi)蜂窩數(shù)據(jù),晚上我關(guān)閉蜂窩數(shù)據(jù),而打開(kāi)無(wú)線網(wǎng)絡(luò),到睡覺(jué)時(shí)我關(guān)閉蜂窩數(shù)據(jù)和無(wú)線網(wǎng)絡(luò),而打開(kāi)飛行模式。假設(shè)在這三個(gè)時(shí)段中其他的所有設(shè)置項(xiàng)都相同,而只有這三個(gè)設(shè)置項(xiàng)不同,那么就可以說(shuō)我的手機(jī)有三種不同的設(shè)置模式,對(duì)應(yīng)著不同的時(shí)間段。那么Run Loop的設(shè)置項(xiàng)是什么呢?那自然就是前文中提到的不同的事件來(lái)源以及觀察者了,比如說(shuō),Run Loop的模式A(Mode A),只包含接收Timer Source事件源的事件消息以及監(jiān)聽(tīng)Run Loop運(yùn)行時(shí)的觀察者,而模式B(Mode B)只包含接收Input Source事件源的事件消息以及監(jiān)聽(tīng)Run Loop準(zhǔn)備休眠時(shí)和退出Run Loop時(shí)的觀察者,如下圖所示:
  再讀蘋果線程配置與Run Loop
  所以說(shuō),Run Loop的模式就是不同類型的數(shù)據(jù)源和不同觀察者的集合,當(dāng)Run Loop運(yùn)行時(shí)要設(shè)置它的模式,也就是告知Run Loop只需要關(guān)心這個(gè)集合中的數(shù)據(jù)源類型和觀察者,其他的一概不予理會(huì)。那么通過(guò)模式,就可以讓Run Loop過(guò)濾掉它不關(guān)心的一些事件,以及避免被無(wú)關(guān)的觀察者打擾。如果有不在當(dāng)前模式中的數(shù)據(jù)源發(fā)來(lái)事件消息,那只能等Run Loop改為包含有該數(shù)據(jù)源類型的模式時(shí),才能處理事件消息。
  在Cocoa框架和Core Foundation框架中,已經(jīng)為我們預(yù)定義了一些Run Loop模式:
  默認(rèn)模式:在NSRunloop中的定義為NSDefaultRunLoopMode,在CFRunloop中的定義為kCFRunLoopDefaultMode。該模式包含的事件源囊括了除網(wǎng)絡(luò)鏈接操作的大多數(shù)操作以及時(shí)間事件,用于當(dāng)前Run Loop處于空閑狀態(tài)等待事件時(shí),以及Run Loop開(kāi)始運(yùn)行時(shí)。NSConnectionReplyMode:該模式用于監(jiān)聽(tīng)NSConnection相關(guān)對(duì)象的返回結(jié)果和狀態(tài),在系統(tǒng)內(nèi)部使用,我們一般不會(huì)使用該模式。NSModalPanelRunLoopMode:該模式用于過(guò)濾在模態(tài)面板中處理的事件(Mac App)。NSEventTrackingRunLoopMode:該模式用于跟蹤用戶與界面交互的事件。模式集合:或者叫模式組,顧名思義就是將多個(gè)模式組成一個(gè)組,然后將模式組認(rèn)為是一個(gè)模式設(shè)置給Run Loop,在NSRunloop中的定義為NSRunLoopCommonModes,在CFRunloop中的定義為kCFRunLoopCommonModes。系統(tǒng)提供的模式組名為Common Modes,它默認(rèn)包含NSDefaultRunLoopMode、NSModalPanelRunLoopMode、NSEventTrackingRunLoopMode這三個(gè)模式。
  以上五種系統(tǒng)預(yù)定的模式中,前四種屬于只讀模式,也就是我們無(wú)法修改它們包含的事件源類型和觀察者類型。而模式組我們可以通過(guò)Core Foundation框架提供的CFRunLoopAddCommonMode(_ rl: CFRunLoop!, _ mode: CFString!)方法添加新的模式,甚至是我們自定義的模式。這里需要注意的是,既然在使用時(shí),模式組是被當(dāng)作一個(gè)模式使用的,那么自然可以給它設(shè)置不同類型的事件源或觀察者,當(dāng)給模式組設(shè)置事件源或觀察者時(shí),實(shí)際是給該模式組包含的所有模式設(shè)置。比如說(shuō)給模式組設(shè)置了一個(gè)監(jiān)聽(tīng)Run Loop準(zhǔn)備休眠時(shí)的觀察者,那么該模式組里的所有模式都會(huì)被設(shè)置該觀察者。
  Input Source
  前文中說(shuō)過(guò),Input Sources接收到各種操作輸入事件消息,然后異步的分派給對(duì)應(yīng)事件處理方法。在Input Sources中又分兩大類的事件源,一類是基于端口事件源(Port-based source),在CFRunLoopSourceRef的結(jié)構(gòu)中為source1,主要通過(guò)監(jiān)聽(tīng)?wèi)?yīng)用程序的Mach端口接收事件消息并分派,該類型的事件源可以主動(dòng)喚醒Run Loop。另一類是自定義事件源(Custom source),在CFRunLoopSourceRef的結(jié)構(gòu)中為source0,一般是接收其他線程的事件消息并分派給當(dāng)前線程的Run Loop,比如performSwlwctor:onThread:。..系列方法,該類型的事件源無(wú)法自動(dòng)喚醒Run Loop,而是需要手動(dòng)將事件源設(shè)置為待執(zhí)行的標(biāo)記,然后再手動(dòng)喚醒Run Loop。雖然這兩種類型的事件源接收事件消息的方式不一樣,但是當(dāng)接收到消息后,對(duì)消息的分派機(jī)制是完全相同的。
  Port-Based Source
  Cocoa框架和Core Foundation框架都提供了相關(guān)的對(duì)象和函數(shù)用于創(chuàng)建基于端口的事件源。在Cocoa框架中,實(shí)現(xiàn)基于端口的事件源主要是通過(guò)NSPort類實(shí)現(xiàn)的,它代表了交流通道,也就是說(shuō)在不同的線程的Run Loop中都存在NSPort,那么它們之間就可以通過(guò)發(fā)送與接收消息(NSPortMessage)互相通信。所以我們只需要通過(guò)NSPort類的類方法port創(chuàng)建對(duì)象實(shí)例,然后通過(guò)NSRunloop的方法將其添加到Run Loop中,或者在創(chuàng)建二級(jí)線程時(shí)將創(chuàng)建好的NSPort對(duì)象傳入即可,無(wú)需我們?cè)僮鱿ⅰ⑾⑸舷挛摹⑹录吹绕渌渲茫加蒖un Loop自行配置好了。而在Core Foundation框架中就比較麻煩一些,大多數(shù)配置都需要我們手動(dòng)配置,在后面會(huì)詳細(xì)舉例說(shuō)明。
  Custom Input Source
  Cocoa框架中沒(méi)有提供創(chuàng)建自定義事件源的相關(guān)接口,我們只能通過(guò)Core Foundation框架中提供的對(duì)象和函數(shù)創(chuàng)建自定義事件源,手動(dòng)配置事件源各個(gè)階段要處理的邏輯,比如創(chuàng)建CFRunLoopSourceRef事件源對(duì)象,通過(guò)CFRunLoopScheduleCallBack回調(diào)函數(shù)配置事件源上下文并注冊(cè)事件源,通過(guò)CFRunLoopPerformCallBack回調(diào)函數(shù)處理接收到事件消息后的邏輯,通過(guò)CFRunLoopCancelCallBack函數(shù)銷毀事件源等等,在后文中會(huì)有詳細(xì)舉例說(shuō)明。
  雖然Cocoa框架沒(méi)有提供創(chuàng)建自定義事件源的相關(guān)對(duì)象和接口,但是它為我們預(yù)定義好了一些事件源,能讓我們?cè)诋?dāng)前線程、其他二級(jí)線程、主線程中執(zhí)行我們希望被執(zhí)行的方法,讓我們看看NSObject中的這些方法:
  func performSelectorOnMainThread(_ aSelector: Selector, withObject arg: AnyObject?, waitUntilDone wait: Bool) func performSelectorOnMainThread(_ aSelector: Selector, withObject arg: AnyObject?, waitUntilDone wait: Bool, modes array: [String]?)
  這兩個(gè)方法允許我們將當(dāng)前線程中對(duì)象的方法讓主線程去執(zhí)行,可以選擇是否阻塞當(dāng)前線程,以及希望被執(zhí)行的方法作為事件消息被何種Run Loop模式監(jiān)聽(tīng)。
  注:如果在主線程中使用該方法,當(dāng)選擇阻塞當(dāng)前線程,那么發(fā)送的方法會(huì)立即被主線程執(zhí)行,若選擇不阻塞當(dāng)前線程,那么被發(fā)送的方法將被排進(jìn)主線程Run Loop的事件隊(duì)列中,并等待執(zhí)行。
  func performSelector(_aSelector: Selector, withObjectanArgument: AnyObject?, afterDelaydelay: NSTimeInterval) func performSelector(_aSelector: Selector, withObjectanArgument: AnyObject?, afterDelaydelay: NSTimeInterval, inModesmodes: [String])
  這兩個(gè)方法允許我們給當(dāng)前線程發(fā)送事件消息,當(dāng)前線程接收到消息后會(huì)依次加入Run Loop的事件消息隊(duì)列中,等待Run Loop迭代執(zhí)行。該方法還可以指定消息延遲發(fā)送時(shí)間及消息希望被何種Run Loop模式監(jiān)聽(tīng)。
  注:該方法中的延遲時(shí)間并不是延遲Run Loop執(zhí)行事件消息的事件,而是延遲向當(dāng)前線程發(fā)送事件消息的時(shí)間。另外,即便不設(shè)置延遲時(shí)間,那么發(fā)送的事件消息也不一定立即被執(zhí)行,因?yàn)樵赗un Loop的事件消息隊(duì)列中可以已有若干等待執(zhí)行的消息。
  func performSelector(_ aSelector: Selector, onThread thr: NSThread, withObject arg: AnyObject?, waitUntilDone wait: Bool) func performSelector(_ aSelector: Selector, onThread thr: NSThread, withObject arg: AnyObject?, waitUntilDone wait: Bool, modes array: [String]?)
  這兩個(gè)方法允許我們給其他二級(jí)線程發(fā)送事件消息,前提是要取得目標(biāo)二級(jí)線程的NSThread對(duì)象實(shí)例,該方法同樣提供了是否阻塞當(dāng)前線程的選項(xiàng)和設(shè)置Run Loop模式的選項(xiàng)。
  注:使用該方法給二級(jí)線程發(fā)送事件消息時(shí)要確保目標(biāo)線程正在運(yùn)行,換句話說(shuō)就是目標(biāo)線程要有啟動(dòng)著的Run Loop。并且保證目標(biāo)線程執(zhí)行的任務(wù)要在應(yīng)用程序代理執(zhí)行applicationDidFinishLaunching:方法前完成,否則主線程就結(jié)束了,目標(biāo)線程自然也就結(jié)束了。
  funcperformSelectorInBackground(_ aSelector: Selector, withObject arg: AnyObject?)
  該方法允許我們?cè)诋?dāng)前應(yīng)用程序中創(chuàng)建一個(gè)二級(jí)線程,并將指定的事件消息發(fā)送給新創(chuàng)建的二級(jí)線程。
  classfunc cancelPreviousPerformRequestsWithTarget(_aTarget: AnyObject)classfunc cancelPreviousPerformRequestsWithTarget(_aTarget: AnyObject, selectoraSelector: Selector, objectanArgument: AnyObject?)
  這兩個(gè)方法是NSObject的類方法,第一個(gè)方法作用是在當(dāng)前線程中取消Run Lop中某對(duì)象通過(guò)performSelector:withObject:afterDelay:方法發(fā)送的所有事件消息執(zhí)行請(qǐng)求。第二個(gè)方法多了兩個(gè)過(guò)濾參數(shù),那就是方法名稱和參數(shù),取消指定方法名和參數(shù)的事件消息執(zhí)行請(qǐng)求。
  Timer Source
  Timer Source顧名思義就是向Run Loop發(fā)送在將來(lái)某一時(shí)間執(zhí)行或周期性重復(fù)執(zhí)行的同步事件消息。當(dāng)某線程不需要其他線程通知而需要自己通知自己執(zhí)行任務(wù)時(shí)就可以用這種事件源。舉個(gè)應(yīng)用場(chǎng)景,在iOS應(yīng)用中,我們經(jīng)常會(huì)用到搜索功能,而且一些搜索框具有自動(dòng)搜索的能力,也就是說(shuō)不用我們點(diǎn)擊搜索按鈕,只需要輸入完我想要搜索的內(nèi)容就會(huì)自動(dòng)搜索,大家想一想如果每輸入一個(gè)字就開(kāi)始立即搜索,不但沒(méi)有意義,性能開(kāi)銷也大,用戶體驗(yàn)自然也很糟糕,我們希望當(dāng)輸入完這句話,或至少輸入一部分之后再開(kāi)始搜索,所以我們就可以在開(kāi)始輸入內(nèi)容時(shí)向執(zhí)行搜索功能的線程發(fā)送定時(shí)搜索的事件消息,讓其在若干時(shí)間后再執(zhí)行搜索任務(wù),這樣就有緩沖時(shí)間輸入搜索內(nèi)容了。
  這里需要注意的是Timer Source發(fā)送給Run Loop的周期性執(zhí)行任務(wù)的重復(fù)時(shí)間是相對(duì)時(shí)間。比如說(shuō)給Run Loop發(fā)送了一個(gè)每隔5秒執(zhí)行一次的任務(wù),每次執(zhí)行任務(wù)的正常時(shí)間為2秒,執(zhí)行5次后終止,假設(shè)該任務(wù)被立即執(zhí)行,那么當(dāng)該任務(wù)終止時(shí)應(yīng)該歷時(shí)30秒,但當(dāng)?shù)谝淮螆?zhí)行時(shí)出現(xiàn)了問(wèn)題,導(dǎo)致任務(wù)執(zhí)行了20秒,那么該任務(wù)只能再執(zhí)行一次就終止了,執(zhí)行的這一次其實(shí)就是第5次,也就是說(shuō)不論任務(wù)的執(zhí)行時(shí)間延遲與否,Run Loop都會(huì)按照初始的時(shí)間間隔執(zhí)行任務(wù),并非按Finish-To-Finish去算的,所以一旦中間任務(wù)有延時(shí),那么就會(huì)丟失任務(wù)執(zhí)行次數(shù)。關(guān)于Timer Source的使用,在后文中會(huì)有詳細(xì)舉例說(shuō)明。
  Run Loop內(nèi)部運(yùn)行邏輯
  在Run Loop的運(yùn)行生命周期中,無(wú)時(shí)無(wú)刻都伴隨著執(zhí)行等待執(zhí)行的各種任務(wù)以及在不同的運(yùn)行狀態(tài)時(shí)通知不同的觀察者,下面我們看看Run Loop中的運(yùn)行邏輯到底是怎樣的:
  通知對(duì)應(yīng)觀察者Run Loop準(zhǔn)備開(kāi)始運(yùn)行。通知對(duì)應(yīng)觀察者準(zhǔn)備執(zhí)行定時(shí)任務(wù)。通知對(duì)應(yīng)觀察者準(zhǔn)備執(zhí)行自定義事件源的任務(wù)。開(kāi)始執(zhí)行自定義事件源任務(wù)。如果有基于端口事件源的任務(wù)準(zhǔn)備待執(zhí)行,那么立即執(zhí)行該任務(wù)。然后跳到步驟9繼續(xù)運(yùn)轉(zhuǎn)。通知對(duì)應(yīng)觀察者線程進(jìn)入休眠。
  如果有下面的事件發(fā)生,則喚醒線程:
  * 接收到基于端口事件源的任務(wù)。
  定時(shí)任務(wù)到了該執(zhí)行的時(shí)間點(diǎn)。Run Loop的超時(shí)時(shí)間到期。Run Loop被手動(dòng)喚醒。
  通知對(duì)應(yīng)觀察者線程被喚醒。
  執(zhí)行等待執(zhí)行的任務(wù)。
  * 如果有定時(shí)任務(wù)已啟動(dòng),執(zhí)行定時(shí)任務(wù)并重啟Run Loop。然后跳到步驟2繼續(xù)運(yùn)轉(zhuǎn)。
  如果有非定時(shí)器事件源的任務(wù)待執(zhí)行,那么分派執(zhí)行該任務(wù)。如果Run Loop被手動(dòng)喚醒,重啟Run Loop。然后跳轉(zhuǎn)到步驟2繼續(xù)運(yùn)轉(zhuǎn)。
  通知對(duì)應(yīng)觀察者已退出Run Loop。
  以上這些Run Loop中的步驟也不是每一步都會(huì)觸發(fā),舉一個(gè)例子:
  1.對(duì)應(yīng)觀察者接收到通知Run Loop準(zhǔn)備開(kāi)始運(yùn)行 -》 3.對(duì)應(yīng)觀察者接收到通知Run Loop準(zhǔn)備執(zhí)行自定義事件源任務(wù) -》 4.開(kāi)始執(zhí)行自定義事件源任務(wù) -》 任務(wù)執(zhí)行完畢且沒(méi)有其他任務(wù)待執(zhí)行 -》 6.線程進(jìn)入休眠狀態(tài),并通知對(duì)應(yīng)觀察者 -》 7.接收到定時(shí)任務(wù)并喚醒線程 -》 8.通知對(duì)應(yīng)觀察者線程被喚醒 -》 9.執(zhí)行定時(shí)任務(wù)并重啟Run Loop -》 2.通知對(duì)應(yīng)觀察者準(zhǔn)備執(zhí)行定時(shí)任務(wù) -》 Run Loop執(zhí)行定時(shí)任務(wù),并在等待下次執(zhí)行任務(wù)的間隔中線程休眠 -》 6.線程進(jìn)入休眠狀態(tài),并通知對(duì)應(yīng)觀察者…
  這里需要注意的一點(diǎn)是從上面的運(yùn)行邏輯中可以看出,當(dāng)觀察者接收到執(zhí)行任務(wù)的通知時(shí),Run Loop并沒(méi)有真正開(kāi)始執(zhí)行任務(wù),所以觀察者接收到通知的時(shí)間與Run Loop真正執(zhí)行任務(wù)的時(shí)間有時(shí)間差,一般情況下這點(diǎn)時(shí)間差影響不大,但如果你需要通過(guò)觀察者知道Run Loop執(zhí)行任務(wù)的確切時(shí)間,并根據(jù)這個(gè)時(shí)間要進(jìn)行后續(xù)操作的話,那么就需要通過(guò)結(jié)合多個(gè)觀察者接收到的通知共同確定了。一般通過(guò)監(jiān)聽(tīng)準(zhǔn)備執(zhí)行任務(wù)的觀察者、監(jiān)聽(tīng)線程進(jìn)入休眠的觀察者、監(jiān)聽(tīng)線程被喚醒的觀察者共同確定執(zhí)行任務(wù)的確切時(shí)間。
?

非常好我支持^.^

(0) 0%

不好我反對(duì)

(0) 0%

再讀蘋果線程配置與Run Loop下載

相關(guān)電子資料下載

      發(fā)表評(píng)論

      用戶評(píng)論
      評(píng)價(jià):好評(píng)中評(píng)差評(píng)

      發(fā)表評(píng)論,獲取積分! 請(qǐng)遵守相關(guān)規(guī)定!

      ?
      主站蜘蛛池模板: 午夜免费无码福利视频麻豆| 免费a毛片| 51久久夜色精品国产| 亚洲 欧美 日本 国产 高清| 日本性xxx| 日本三级黄色大片| 青青草AV国产精品| 欧美成人一区二免费视频| 免费毛片在线视频| 蜜芽在线影片| 免费看黄的片多多APP下载| 麻豆一二三区果冻| 蜜桃传媒在线播放| 男生在床上脱美女 胸| 免费99精品国产自在现线| 免费人妻AV无码专区五月| 免费乱理伦片在线观看夜| 男人插女人动态图| 欧美一区二区日韩一区二区| 欧美高清videossexo| 欧美亚洲日韩在线在线影院| 日本中文字幕伊人成中文字幕| 色多多污网站在线观看| 少妇精油按摩| 小便japanesewctv| 亚洲免费无l码中文在线视频| 亚洲精品在线不卡| 中文字幕AV在线一二三区| 91热久久免费频精品99欧美| 99久久无码热高清精品| 潮 喷女王cytherea| 国产精品www视频免费看| 国产午夜永久福利视频在线观看 | 国产成人精品免费视频大全办公室 | 各种肉黄浪荡故事集| 国产精品久久久精品日日| 国产亚洲精品久久777777| 久久AAAA片一区二区| 男人吃奶摸下挵进去啪啪| 日本无码毛片久久久九色综合| 色欲档案之麻雀台上淫|