(五十六)iOS多線程之NSOperation

NSOpertation是一套OC的API,是對GCD進行的Cocoa抽象。

NSOperation有兩種不同類型的隊列,主隊列和自定義隊列。

主隊列運行于主線程上,自定義隊列在后臺運行。


【NSBlockOperation】

通過Block創建任務,下面比較主隊列和自定義隊列的區別:

將自定義隊列聲明為成員變量,并進行初始化:

@property (nonatomic, strong) NSOperationQueue *myqueue;
self.myqueue = [[NSOperationQueue alloc] init];

獲取主隊列的方法為[NSOperationQueue mainQueue]。

隊列有一個方法addOperationWithBlock方法用于添加一個用Block描述的任務。

具體代碼為:

- (void)NSBlockOperation{// 自定義隊列在子線程中運行。[self.myqueue addOperationWithBlock:^{NSLog(@"%@",[NSThread currentThread]);}];// 主隊列任務在主線程中運行。[[NSOperationQueue mainQueue] addOperationWithBlock:^{NSLog(@"%@",[NSThread currentThread]);}];}
執行這個方法,得到的結果如下,可見與上面的描述相符。

2015-02-17 10:46:15.308 NSOpertaion[709:17138] <NSThread: 0x7b9aa440>{number = 2, name = (null)}
2015-02-17 10:46:15.319 NSOpertaion[709:17067] <NSThread: 0x7b978550>{number = 1, name = main}


【NSInvocationOperation】

需要定義一個回調方法,好處是可以接收一個id類型的object作為消息。

例如:

- (void)NSInvocationOperation{NSDictionary *msg = @{@"name" : @"op",@"message" : @"hello"};NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(InvocationCall:) object:msg];[self.myqueue addOperation:op];}

實現回調方法:

- (void)InvocationCall:(id)obj{NSLog(@"%@ with object %@",[NSThread currentThread],obj);
}

調用后,打印的結果如下,可以看到object對象被傳了過來。

2015-02-17 10:56:03.764 NSOpertaion[812:26537] <NSThread: 0x7ba6eb10>{number = 2, name = (null)} with object {message = hello;name = op;
}

【任務執行順序】

在默認情況下,自定義隊列是并行隊列,執行無序;而主隊列為串行隊列,有序執行。下面進行實驗驗證說法:

    // 自定義隊列在子線程中運行。for (int i = 0; i < 9; i++) {[self.myqueue addOperationWithBlock:^{NSLog(@"%@ with no %d",[NSThread currentThread],i);}];}// 主隊列任務在主線程中運行。for (int i = 0; i < 9; i++) {[[NSOperationQueue mainQueue] addOperationWithBlock:^{NSLog(@"%@ with no %d",[NSThread currentThread],i);}];}

執行結果如下,可見與上面的描述相同。

2015-02-17 11:04:08.421 NSOpertaion[919:32337] <NSThread: 0x7bf91f50>{number = 9, name = (null)} with no 6
2015-02-17 11:04:08.421 NSOpertaion[919:32331] <NSThread: 0x7bf91c10>{number = 4, name = (null)} with no 1
2015-02-17 11:04:08.421 NSOpertaion[919:32338] <NSThread: 0x7bf915c0>{number = 6, name = (null)} with no 5
2015-02-17 11:04:08.421 NSOpertaion[919:32336] <NSThread: 0x7dab62c0>{number = 7, name = (null)} with no 4
2015-02-17 11:04:08.421 NSOpertaion[919:32339] <NSThread: 0x7dab61b0>{number = 3, name = (null)} with no 7
2015-02-17 11:04:08.421 NSOpertaion[919:32330] <NSThread: 0x7dab6110>{number = 2, name = (null)} with no 0
2015-02-17 11:04:08.421 NSOpertaion[919:32341] <NSThread: 0x7d97b3f0>{number = 5, name = (null)} with no 8
2015-02-17 11:04:08.421 NSOpertaion[919:32328] <NSThread: 0x7be6d450>{number = 10, name = (null)} with no 3
2015-02-17 11:04:08.421 NSOpertaion[919:32329] <NSThread: 0x7dab6450>{number = 8, name = (null)} with no 2
2015-02-17 11:04:08.448 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 0
2015-02-17 11:04:08.449 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 1
2015-02-17 11:04:08.449 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 2
2015-02-17 11:04:08.449 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 3
2015-02-17 11:04:08.450 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 4
2015-02-17 11:04:08.450 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 5
2015-02-17 11:04:08.450 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 6
2015-02-17 11:04:08.450 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 7
2015-02-17 11:04:08.450 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 8


【自定義隊列順序執行】

使用NSBlockOperation對象的addDependency設置依賴關系,只有依賴的對象執行完畢后,自己才能執行。

例如下面的例子,三個任務要順序執行,先下載,再處理,最后顯示,通過這樣的設定可以保證順序:

- (void)SerialOperation{NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{NSLog(@"下載");}];NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{NSLog(@"處理");}];NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{NSLog(@"顯示");}];[op2 addDependency:op1];[op3 addDependency:op2];[self.myqueue addOperation:op1];[self.myqueue addOperation:op2];[self.myqueue addOperation:op3];}
注意這個執行和串行隊列的異步任務不同點是,串行隊列的異步任務僅僅開一個線程;自定義隊列的順序執行可能開辟多個但不會太多個線程。

注意上面的代碼有一定的問題,因為顯示只有主線程可以處理,所以op3應該放入主線程。

Tip:依賴關系可以跨隊列,因此op3依賴op2在主線程中仍然有效,只需要修改op3的入隊代碼為:

[[NSOperationQueue mainQueue] addOperation:op3];

Tip:注意避開循環依賴,程序會崩潰



【設定多線程的最大開銷】

設定同時執行的最大線程數:通過隊列的setMaxConcurrentOperationCount方法來設定,例如:

[self.myqueue setMaxConcurrentOperationCount:3];

應用場景:網絡通信,例如3G開3個子線程,WIFI開6個子線程。

Tip:線程的開銷主要是CPU和內存,還會耗電,因此應該考慮軟件的能耗。


Tip:AFNetworing的底層是使用GCD開發的,接口是NSOperation。


轉載于:https://www.cnblogs.com/aiwz/p/6154194.html

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

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

相關文章

android 系統源碼調試 局部變量值_如何方便快速的整編Android 9.0系統源碼?

點擊上方“劉望舒”&#xff0c;選擇“星標”多點在看&#xff0c;就是真愛&#xff01;作者 : 劉望舒 | 來源 &#xff1a;劉望舒的博客地址&#xff1a;http://liuwangshu.cn/framework/aosp/3-compiling-aosp.html前言在上一篇文章是時候下載Android 9.0系統源碼了中&…

boost 文件操作

如果要簡單處理文件和文件夾的時候&#xff08;刪除、重命名等&#xff09;&#xff0c;使用Windows的系統函數會十分麻煩&#xff0c;可以嘗試一下使用Boost庫來進行處理 頭文件 #include <boost/filesystem.hpp>如果要獲得每次處理的結果錯誤碼&#xff0c;需要加上頭…

讓“是男人就下到100層”在Android平臺上跑起來

原工程:https://github.com/jeekun/DownFloors 移植后的代碼&#xff1a;HelloCpp.zip 移植后的APK&#xff1a;HelloCpp.apk 說明&#xff1a;&#xff08;cocos2d-x版本是“ 2.2&#xff09; 1.該工程是直接在HelloCpp上修改完成,所以包名也不修改了 2.原工程里面可能是采用g…

Codeforces Round #277 (Div. 2) 題解

Codeforces Round #277 (Div. 2)A. Calculating Functiontime limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputstandard outputFor a positive integer n lets define a function f: f(n)???-?1??2?-?3??..??(?-?1)nn Your …

QT 邊框圓角處理

平時的邊框是平角的&#xff1a; 如果需要圓角的話&#xff0c;就要加stylesheet加上這個&#xff1a; border-radius:3px;比如&#xff1a; QPushButton{ border-radius:3px; }就變成圓角了&#xff1a; px前面的數字越大就越圓&#xff0c;比如5px比3px圓 假如只需要某一…

3級調度 fpga_Vivado HLS學習筆記——1.了解FPGA架構

本篇文章為本人學習Xilinx的Vivado HLS教程記錄的學習筆記&#xff0c;僅供學習參考。Vivado HLS官方視頻教程&#xff1a;優酷視頻?v.youku.com目錄&#xff1a; Vivado HLS課程簡介FPGA與CPU、GPU、DSP的區別FPGA的優勢Xilinx FPGA架構:邏輯單元、算術邏輯單元、存儲單元使用…

[LeetCode]Maximum Depth of Binary Tree

Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. 思考&#xff1a;DFS。 /*** Definition for binary tree* struct TreeNode {* int val;* Tree…

BZOJ2435 [Noi2011]道路修建

這是NOI11年題&#xff0c;你在逗我&#xff1f; 直接dfs就可以了&#xff0c;Linux下貌似不會爆棧。。。 1 /**************************************************************2 Problem: 24353 User: rausen4 Language: C5 Result: Accepted6 Time:5184 …

Qt異常結束程序無法重新運行

有時候代碼有問題會導致qt異常結束 修改完后重新運行又會出現 查看任務管理器又沒有這個進程 可以使用資源管理器打開看看 也可以考慮使用process explorer查看 發現程序掛起來&#xff0c;結束掉它就可以重新運行了

hadooppythonsql_半小時搞定Hadoop+Mysql+Hive+Python

1. 說明搭建過Hadoop集群的小伙伴一定知道&#xff0c;如果不用docker&#xff0c;半小時配好HadoopMysqlHive(后簡稱Hive)肯定是胡吹&#xff0c;有了Docker鏡像&#xff0c;沒有說明文檔&#xff0c;配好了也不一定會用。本文將介紹如何在半小時內&#xff0c;讓Hive在你的Li…

PHP 切割字符串 點號 不用雙斜杠

$name "tupian.png"; $nameArr explode(".", $name); 習慣了Java的程序員容易寫成 $nameArr explode("\\.", $name);//在PHP中是不正確的轉載于:https://www.cnblogs.com/wuyou/p/3463425.html

Qt新添加的類無法鏈接

通過這個方法給工程添加了個類&#xff1a; 編譯的時候就出現了這個問題&#xff1a; 執行一下qmake 然后再重新構建項目就可以了

URAL 1830 Help in the RNOS 思路,讀題 難度:1

http://acm.timus.ru/problem.aspx?space1&num1830 這道題需要理解題目操作的意思, 要更改第i位的狀態,第i-1位必須激活為1,0-i-2位必須為0,如果0-i-1位開始時全為0,那么從0位開始進行操作 一.首先考慮對于0-i-1位都是0,需要更改i位的情況,需要 1.更改i-1位,2.按一下打開下…

openssh升級sftp_OpenSSH 8.2 發布 包括 sftp 客戶端和服務器支持

OpenSSH 8.2 發布了。OpenSSH 是 100% 完整的 SSH 協議 2.0 版本的實現&#xff0c;并且包括 sftp 客戶端和服務器支持。此版本變化不少&#xff0c;其中有兩個地方值得特別關注。一個是新特性&#xff0c;此版本增加了對 FIDO/U2F 硬件身份驗證器的支持。FIDO/U2F 是廉價硬件雙…

任務隊列摘自新鋒

在開發C程序時&#xff0c;一般在吞吐量、并發、實時性上有較高的要求。設計C程序時&#xff0c;總結起來可以從如下幾點提高效率&#xff1a; l 并發l 異步l 緩存下面將我平常工作中遇到一些問題例舉一二&#xff0c;其設計思想無非以上三點。 1任務隊列 1.1 以生產者-消…

C++容器遍歷時刪除元素

vector 錯誤做法 這樣做會在遍歷過程中越界導致程序崩潰 std::vector<int> vecInt({ 1, 3, 2, 1, 4, 1 });for (auto i vecInt.begin(); i ! vecInt.end() ; i) {if (*i 1) {vecInt.erase(i);}}正確做法 std::vector<int> vecInt({ 1, 3, 2, 1, 4, 1 });for (a…

按鈕圖片拉伸_圖片墻有多香?高手都在用的PPT封面制作技巧!

大家好&#xff0c;我是李導~這次&#xff0c;冬天是真的來了&#xff0c;不知道大家有沒有感覺&#xff0c;每次冷空氣真正襲來之前我們都會以為今年是個暖冬&#xff0c;結果突然有一天氣溫從20度直降到個位數&#xff0c;我們都會認為今年比以往的冬天都冷。但是&#xff0c…

POJ 1745 Divisibility【DP】

題意&#xff1a;給出n,k,n個數&#xff0c;在這n個數之間任意放置,-號&#xff0c;稱得到的等式的值能夠整除k則為可劃分的&#xff0c;否則為不可劃分的。 自己想的是枚舉&#xff0c;將所有得到的等式的和算出來&#xff0c;再判斷它是否能夠整除k&#xff0c;可是有10000個…

三種root的修補方式

三種root的修補方式 system/core/adb/abd.c adbd漏洞&#xff0c;請看abd.c的第917行/* then switch user and group to "shell" */ if (setgid(AID_SHELL) ! 0) { exit(1); } if (setuid(AID_SHELL) ! 0) { exit(1); …

數據挖掘十大經典算法

國際權威的學術組織the IEEE International Conference on Data Mining (ICDM) 2006年12月評選出了數據挖掘領域的十大經典算法&#xff1a;C4.5, k-Means, SVM, Apriori, EM, PageRank, AdaBoost, kNN, Naive Bayes, and CART. 不不過選中的十大算法&#xff0c;事實上參加評選…