NSOperationQueue 的簡單介紹

NSOperationQueue 是調(diào)節(jié)操作執(zhí)行的隊(duì)列。

操作隊(duì)列根據(jù)NSOperation對象的優(yōu)先級和準(zhǔn)備情況執(zhí)行排隊(duì)的NSOperation對象彩匕。operation添加到一個(gè)隊(duì)列中之后,operation將保持在隊(duì)列中媒区,直到它完成任務(wù)驼仪。添加后,不能直接從隊(duì)列中刪除operation袜漩。

注意:

操作隊(duì)列會retain 操作绪爸,直到它們完成。并且操作隊(duì)列自身也會被retain宙攻,直到所有的操作完成奠货。使用未完成的operation掛起 操作隊(duì)列會導(dǎo)致內(nèi)存泄漏

操作隊(duì)列的更多信息可以查看官方文檔

確定執(zhí)行順序

隊(duì)列中的操作根據(jù)其準(zhǔn)備情況,優(yōu)先級和操作依賴性進(jìn)行執(zhí)行座掘。 如果所有排隊(duì)的操作都具有相同的 queuePriority递惋, 并且 ready 屬性返回 YES ,則會按照添加到隊(duì)列的順序執(zhí)行溢陪。 否則萍虽,操作隊(duì)列總是執(zhí)行相對于其他操作具有最高優(yōu)先級的操作。

我們不應(yīng)該依賴隊(duì)列來確保操作的特定執(zhí)行順序形真,因?yàn)椴僮鳒?zhǔn)備情況的更改可能會改變執(zhí)行順序杉编。 操作依賴為操作提供了一個(gè)絕對的執(zhí)行順序,即使這些操作位于不同的操作隊(duì)列。 操作對象直到它依賴的所有的操作完成執(zhí)行之前都不會被視為可以執(zhí)行邓馒。

取消操作

結(jié)束任務(wù)并不一定意味著operation完成該任務(wù)嘶朱,操作也可以被取消。取消一個(gè)operation對象會將其留在隊(duì)列中绒净,但是會通知對象盡可能快的 stop 其任務(wù)见咒。對于正在執(zhí)行的操作,這意味著operation對象的工作代碼必須檢查取消狀態(tài)挂疆、停止正在做的事情,并標(biāo)記自身為finished下翎。 對于正在排隊(duì)但尚未執(zhí)行的操作缤言,隊(duì)列必須調(diào)用operation對象的start方法,以便于他可以處理取消事件并將自身標(biāo)記為finished.

注意:

取消一個(gè)操作會導(dǎo)致操作忽略它可能具有的依賴關(guān)系视事〉ㄏ簦可能會使隊(duì)列盡可能快地執(zhí)行operation的start方法。 start 方法反過來將操作轉(zhuǎn)至 finished 狀態(tài)俐东,以便它可以從隊(duì)列中移除跌穗。

KVO-兼容屬性

NSOperationQueue 類是支持KVC和KVO的。我們可以根據(jù)需要觀察以下屬性:

  • @property(readonly, copy) NSArray<__kindof NSOperation *> *operations;

  • @property(readonly) NSUInteger operationCount;

  • @property NSInteger maxConcurrentOperationCount;

  • @property(getter=isSuspended) BOOL suspended;

  • @property(copy) NSString *name;

線程安全

使用單個(gè) NSOperationQueue 對象是多線程安全的虏辫,不需要使用額外的鎖來同步對該對象的訪問

操作隊(duì)列使用 Dispatch 框架來啟動(dòng)操作的執(zhí)行蚌吸。因此,操作總是在一個(gè)單獨(dú)的線程上執(zhí)行砌庄,而不管它們是被指定為同步還是異步羹唠。

主要方法

訪問特定操作隊(duì)列
  • @property(class, readonly, strong) NSOperationQueue *mainQueue;

    返回與主線程相關(guān)聯(lián)的操作隊(duì)列

    返回的隊(duì)列在主線程中一次執(zhí)行一個(gè)操作。主線程上的操作的執(zhí)行與其他必須在主線程上執(zhí)行的任務(wù)交替娄昆,例如服務(wù)事件和UI的更新佩微。隊(duì)列在runloop的 NSRunLoopCommonModes 模式下執(zhí)行這些操作。隊(duì)列的underlyingQueue屬性的值是主線程的調(diào)度隊(duì)列萌焰,該屬性不能設(shè)置為其他值哺眯。

  • @property(class, readonly, strong) NSOperationQueue *currentQueue;

    返回在當(dāng)前線程運(yùn)行的操作隊(duì)列。

管理隊(duì)列中的操作
  • - (void)addOperation:(NSOperation *)op;

    添加指定操作到receiver扒俯。

    一旦添加奶卓,該操作將會被保留在隊(duì)列中,直到它完成執(zhí)行

    重點(diǎn):

    一個(gè)操作對象一次最多只能有一個(gè)操作隊(duì)列陵珍,如果操作已經(jīng)在其他隊(duì)列中寝杖,調(diào)用該方法會拋出 NSInvalidArgumentException 異常。同樣地互纯,如果操作正在執(zhí)行或者已經(jīng)結(jié)束執(zhí)行瑟幕,該方法也會引發(fā) NSInvalidArgumentException 異常

  • - (void)addOperations:(NSArray<NSOperation *> *)ops waitUntilFinished:(BOOL)wait;

    添加指定的操作到隊(duì)列中。

    參數(shù):

    ops: 要添加到隊(duì)列的操作

    wait: 如果為YES,則阻塞當(dāng)前線程只盹,直到所有指定的操作都執(zhí)行結(jié)束辣往。如果為NO,操作將被添加到隊(duì)列中殖卑,并直接返回給調(diào)用者站削。


    操作對象一次最多只能在一個(gè)操作隊(duì)列中,如果操作正在執(zhí)行或者已經(jīng)finished孵稽,則不能添加到隊(duì)列中许起。對于ops參數(shù)中的任意操作,如果有任何錯(cuò)誤條件菩鲜,該方法都會拋出 NSInvalidArgumentException 異常园细。

    一旦添加,operation將保留在隊(duì)列中接校,直到operation的 finished方法返回YES猛频。

  • - (void)addOperationWithBlock:(void (^)(void))block;

    將指定的block包裝到operation 中,并將其添加到receiver中蛛勉。

    該方法首先將一個(gè)block封裝到一個(gè)操作對象中鹿寻,然后將其添加到receiver中。 不應(yīng)嘗試獲取對新創(chuàng)建的操作對象的引用或確定其類型信息诽凌。

  • @property(readonly, copy) NSArray<__kindof NSOperation *> *operations;

    當(dāng)前在隊(duì)列中的操作
    該數(shù)組屬性包含零個(gè)或多個(gè) NSOperation 對象毡熏,按照添加到隊(duì)列中的順序。該數(shù)組不一定反映操作的執(zhí)行順序皿淋。

    可以使用該屬性在任何給定的時(shí)刻訪問排隊(duì)的操作招刹。直到操作完成它們的任務(wù)之前都會保留在隊(duì)列中。因此窝趣,該數(shù)組可能包含正在執(zhí)行或等待執(zhí)行的操作疯暑。

    可以使用KVO監(jiān)測該屬性值的更改。

  • @property(readonly) NSUInteger operationCount;

    當(dāng)前在隊(duì)列中的操作數(shù)量哑舒。

    由于隊(duì)列中的操作數(shù)量隨著這些操作的執(zhí)行完成而發(fā)生變化妇拯,該屬性的值反映了訪問該屬性時(shí)的瞬間的操作的數(shù)量。當(dāng)使用該值時(shí)洗鸵,操作的實(shí)際數(shù)量可能會有所不同越锈。因此,不應(yīng)該使用該值用于對象的枚舉或其他精確計(jì)算膘滨。

    可以使用KVO監(jiān)測該屬性的值甘凭。

  • - (void)cancelAllOperations;

    取消所有排隊(duì)或正在執(zhí)行的操作

    該方法調(diào)用當(dāng)前隊(duì)列中所有操作的cancel方法。

    取消操作并不會自動(dòng)從隊(duì)列中移除操作火邓,或者停止正在執(zhí)行的操作丹弱。對于排隊(duì)且等待執(zhí)行的操作德撬,
    隊(duì)列必須仍嘗試執(zhí)行該操作,然后才能確認(rèn)該操作已被取消并將其移至finished狀態(tài)躲胳。對于正在執(zhí)行的操作蜓洪,操作對象本身必須檢查取消和停止正在執(zhí)行的操作,以便于該操作可以移至finished狀態(tài)坯苹。在這兩種情況下隆檀,一個(gè)finished(或取消的)操作仍然有機(jī)會在從隊(duì)列中移除之前執(zhí)行它的 completion block。

  • - (void)waitUntilAllOperationsAreFinished;

    阻塞當(dāng)前線程粹湃,直到receiver的所有排隊(duì)和正在執(zhí)行的操作完成執(zhí)行恐仑。

    當(dāng)調(diào)用該方法時(shí),會阻塞當(dāng)前線程再芋,并等待receiver的當(dāng)前和排隊(duì)的operation完成其執(zhí)行菊霜。當(dāng)前線程被阻塞時(shí),receiver將繼續(xù)執(zhí)行已經(jīng)排隊(duì)的操作并監(jiān)測正在執(zhí)行的操作济赎。在此期間,當(dāng)前線程不能添加操作到隊(duì)列中记某,但其他線程可能會司训。一旦所有等待的操作都完成了,該方法會返回液南。

    如果隊(duì)列中沒有操作壳猜,該方法將直接返回。

管理操作的執(zhí)行
  • @property NSQualityOfService qualityOfService;

    該屬性指定了應(yīng)用于添加到隊(duì)列的操作對象的服務(wù)等級滑凉。如果操作對象具有一個(gè)明確的服務(wù)等級設(shè)置统扳,則使用該值。該屬性的默認(rèn)值取決于創(chuàng)建隊(duì)列的方式畅姊。對于自己創(chuàng)建的隊(duì)列咒钟,默認(rèn)值是NSOperationQualityOfServiceBackground。對于mainQueue方法返回的隊(duì)列若未,默認(rèn)值是NSOperationQualityOfServiceUserInteractive朱嘴,并且不能更改。

    服務(wù)級別會影響操作對象訪問系統(tǒng)資源(比如CPU時(shí)間粗合、網(wǎng)絡(luò)資源萍嬉、磁盤資源等)的優(yōu)先級。具有更高質(zhì)量的服務(wù)級別的操作比系統(tǒng)資源具有更高的優(yōu)先級隙疚,以便它們可以更快速的執(zhí)行任務(wù)壤追。可以使用服務(wù)級別來確保用戶顯式請求的操作優(yōu)先于其他不太重要的操作供屉。

  • @property NSInteger maxConcurrentOperationCount;

    可以同時(shí)執(zhí)行的隊(duì)列操作的最大數(shù)量行冰。

    此屬性中的值僅影響當(dāng)前隊(duì)列同時(shí)執(zhí)行的操作溺蕉。 其他操作隊(duì)列也可以并行執(zhí)行其最大數(shù)量的操作。

    減少并發(fā)操作的數(shù)量不會影響正在執(zhí)行的任何操作资柔。指定該屬性值為 NSOperationQueueDefaultMaxConcurrentOperationCount(推薦)時(shí)焙贷,系統(tǒng)會根據(jù)系統(tǒng)條件設(shè)置最大數(shù)量的操作。

    該屬性的默認(rèn)值是 NSOperationQueueDefaultMaxConcurrentOperationCount贿堰≌奚郑可以使用KVO監(jiān)測該屬性的值。

    NSOperationQueueDefaultMaxConcurrentOperationCount這個(gè)數(shù)字是根據(jù)當(dāng)前系統(tǒng)條件動(dòng)態(tài)確定的羹与。

暫停執(zhí)行
  • @property(getter=isSuspended) BOOL suspended;

    當(dāng)該屬性的值是NO時(shí)故硅,隊(duì)列會主動(dòng)啟動(dòng)隊(duì)列中準(zhǔn)備執(zhí)行的操作。將該屬性設(shè)置為YES將阻止隊(duì)列啟動(dòng)任何排隊(duì)的操作纵搁。但已經(jīng)執(zhí)行的操作將繼續(xù)執(zhí)行吃衅。可以繼續(xù)添加操作到暫停的隊(duì)列中腾誉,但是這些操作在該屬性變?yōu)镹O之前都不會執(zhí)行徘层。

    只有在完成執(zhí)行時(shí),操作才會從隊(duì)列中移除利职。但是趣效,為了完成執(zhí)行,必須首先啟動(dòng)一個(gè)操作猪贪。因?yàn)橐粋€(gè)暫停的操作不會開啟任何新的操作跷敬,所以它不會移除當(dāng)前排隊(duì)且未執(zhí)行的任何操作(包括取消的操作)

    可以使用KVO監(jiān)測該屬性的值。該屬性的默認(rèn)值為NO

隊(duì)列的配置
  • @property(copy) NSString *name;

    操作隊(duì)列的名稱热押。提供了一種在運(yùn)行時(shí)標(biāo)識操作隊(duì)列的方式西傀。

    該屬性的默認(rèn)值是包含操作隊(duì)列內(nèi)存地址的字符串⊥把ⅲ可以使用KVO監(jiān)測該屬性值的變化

  • @property(assign) dispatch_queue_t underlyingQueue;

    用于執(zhí)行操作的dispatch 隊(duì)列

    該屬性的默認(rèn)值為 nil拥褂。 可以將此屬性的值設(shè)置為一個(gè)現(xiàn)有的調(diào)度隊(duì)列,以使隊(duì)列操作與提交到該調(diào)度隊(duì)列的 block 相關(guān)聯(lián)鬼廓。

    只有隊(duì)列中沒有操作時(shí)才應(yīng)該設(shè)置該屬性的值肿仑。當(dāng)operationCount屬性的值不等于0時(shí)設(shè)置該屬性的值會引發(fā)NSInvalidArgumentException異常。此屬性的值不能是dispatch_get_main_queue返回的值碎税。

    注意:

    如果 OS_OBJECT_IS_OBJC 為YES,該屬性會自動(dòng)retain 其分配的隊(duì)列

資料來源:
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尤慰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子雷蹂,更是在濱河造成了極大的恐慌伟端,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匪煌,死亡現(xiàn)場離奇詭異责蝠,居然都是意外死亡党巾,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門霜医,熙熙樓的掌柜王于貴愁眉苦臉地迎上來齿拂,“玉大人,你說我怎么就攤上這事肴敛∈鸷#” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵医男,是天一觀的道長砸狞。 經(jīng)常有香客問我,道長镀梭,這世上最難降的妖魔是什么刀森? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮报账,結(jié)果婚禮上垛叨,老公的妹妹穿的比我還像新娘爆土。我一直安慰自己西潘,他們只是感情好嘴办,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布狗超。 她就那樣靜靜地躺著砌些,像睡著了一般逗嫡。 火紅的嫁衣襯著肌膚如雪询微。 梳的紋絲不亂的頭發(fā)上浊服,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天统屈,我揣著相機(jī)與錄音,去河邊找鬼牙躺。 笑死愁憔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的孽拷。 我是一名探鬼主播吨掌,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼脓恕!你這毒婦竟也來了膜宋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤炼幔,失蹤者是張志新(化名)和其女友劉穎秋茫,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乃秀,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肛著,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年圆兵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枢贿。...
    茶點(diǎn)故事閱讀 39,731評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡殉农,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出局荚,到底是詐尸還是另有隱情超凳,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布危队,位于F島的核電站聪建,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏茫陆。R本人自食惡果不足惜金麸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望簿盅。 院中可真熱鬧挥下,春花似錦、人聲如沸桨醋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喜最。三九已至偎蘸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瞬内,已是汗流浹背迷雪。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留虫蝶,地道東北人章咧。 一個(gè)月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像能真,于是被迫代替她去往敵國和親赁严。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時(shí)...
    歐辰_OSR閱讀 29,373評論 8 265
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,097評論 1 32
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理粉铐,服務(wù)發(fā)現(xiàn)疼约,斷路器,智...
    卡卡羅2017閱讀 134,652評論 18 139
  • NSOperation是一個(gè)抽象類秦躯,代表與單個(gè)任務(wù)相關(guān)聯(lián)的代碼和數(shù)據(jù)忆谓。 由于NSOperation是一個(gè)抽象類,所...
    哆啦_閱讀 1,460評論 1 4
  • 玄奘西行求經(jīng)的事跡一再演繹踱承,《大唐玄奘》并沒有標(biāo)新立異倡缠,但透過一幀幀精美的畫面哨免,仍然令人觸動(dòng)。 玄奘沒有拿到天竺簽...
    張永勝_永往直前閱讀 838評論 3 2