NSOperation

4.NSOperation

  • **NSOperation的兩個核心概念 : **操作和隊列
  • **介紹 : **
    1.NSOperation是一個抽象類,并不具備封裝操作的能力,必須使用它的子類
    NSOperation的子類
1.NSInvocationOperation
2.NSBlockOperation
3.自定義繼承NSOperation的子類,實現(xiàn)子類內(nèi)部的main(對象方法)方法

2.只用配合使用NSOperation和NSOperationQueue才能實現(xiàn)多線程編程
通過NSOperation和NSOperationQueue實現(xiàn)多線程的具體步驟:

1.將需要的操作封裝到一個NSOperation對象中
2.將NSOperation對象添加到NSOperationQueue隊列對象中
3.系統(tǒng)會自動將NSOperationQueue隊列對象中的NSOperation對象取出
4.將取出的NSOperation對象封裝的操作方法,放到一條新線程中執(zhí)行

操作 - 封裝操作的幾種方式

**方式一 : **NSInvocationOperation
作用:封裝操作,默認是不會開啟線程的,只會在當前的線程中執(zhí)行操作

NSInvocationOperation * iop1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(test) object:nil];
[iop1 start];//開啟任務
//注意:這里沒有將操作添加到隊列中,是不會開心新的線程去執(zhí)行操作的,只會在當前線程中同步執(zhí)行操作

**方式二 : **NSBlockOperation
作用:封裝操作,默認是不會開啟線程的,只有在一個操作內(nèi)有多個任務或者將操作添加到隊列中,才會開啟線程

NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"1----%@",[NSThread currentThread]);
    }];
//2.開啟任務
    [op1 start];
//追加任務(會自動開子線程,任務的執(zhí)行時并發(fā)執(zhí)行的)
    [op3 addExecutionBlock:^{//追加的操作有可能在子線程中執(zhí)行,也有主線程中執(zhí)行
        NSLog(@"4----%@",[NSThread currentThread]);
    }];

**注意 : **
1.追加任務,會自動開啟子線程,并且任務的執(zhí)行是并發(fā)執(zhí)行的(追加的任務不一定是在子線程中執(zhí)行,也有可能是在主線程中執(zhí)行)
2.當操作中的任務數(shù)量大于1時,就會開啟子線程(其實就是和1中說的一樣)

**方式三 : **自定義NSOperation
封裝操作:重寫main方法,將所有的的操作都放在main方法里面,說明start方法也是調(diào)用main方法的

在自定義的NSOperation類的@implementation中的main方法
//在子類內(nèi)重寫main方法實現(xiàn)任務
-(void)main
{
       NSLog(@"-----customClas-----%@",[NSThread currentThread]);
}

在外界的調(diào)用
//默認不會開線程,只會在當前線程內(nèi)執(zhí)行任務 
ZHJOperation * customOp = [[ZHJOperation alloc] init];
//注意:自定義的NSOperation也需要調(diào)用start方法才能執(zhí)行,但是僅僅是這樣,是不會開啟子線程的,只有將操作添加到隊列中,才會開啟子線程
[customOp start];

隊列 NSOperationQueue

  • NSOperation的隊列和GCD中的隊列相似,只不過NSOperation中的隊列分為主隊列和非主隊列
    • 主隊列
      **特點 : **
      1)所有的任務都是在主隊列中執(zhí)行的
      2)主隊列是一個串行的隊列
      **獲取隊列以及添加操作到隊列 : **
 //創(chuàng)建隊列-主隊列
NSOperationQueue * queue = [NSOperationQueue mainQueue]; 
//將操作添加到隊列中
[queue addOperation:operation];  
  • 非主隊列
    **特點 : ** 同時具備串行和并發(fā)的功能,默認情況下是并發(fā)的,可以手動設(shè)置為串行隊列,通過設(shè)置最大并發(fā)數(shù)屬性來更改.
    **獲取隊列以及添加操作到隊列 : **
//獲取隊列 - 非主隊列
NSOperationQueue*queue = [[NSOperationQueue alloc]init];
//將操作添加到隊列中
[queue addOperation:op1];

**注意 : **將操作添加到隊列中的方法"addOperation:",已經(jīng)在內(nèi)部執(zhí)行了start方法了,所以在將操作添加到隊列后,不再需要執(zhí)行start方法來執(zhí)行操作了
**
由于NSInvocationOperation/NSBlockOperation/自定義的NSOperation將操作添加到隊列的方法是一樣的,同上面介紹主隊列或非主隊列時的將操作添加到隊列中樣,所以就不再重復編寫
**
**
簡便方法(僅限于NSBlockOperation類) : **也可以說是快速將操作加入到隊列的方法,這個方法不需要創(chuàng)建操作

//通過addOperationWithBlock:添加的操作,會比通過NSBlockOperation創(chuàng)建的操作先執(zhí)行
    [queue addOperationWithBlock:^{
        NSLog(@"4-----------%@",[NSThread currentThread]);
    }];
  • 最大并發(fā)數(shù)
    **作用 : **同一時間內(nèi),最多可以處理的任務的數(shù)量
    @property NSInteger maxConcurrentOperationCount;
    注意:
    1.隊列默認是并發(fā)隊列
    2.“-1”在計算機中,標識的是最大值(即默認是不受限制的),這里同樣表示最大值, 最大并發(fā)數(shù), 具體多少根據(jù)系統(tǒng) CPU 的使用率, 分配 并發(fā)數(shù)
    3.在操作添加到隊列之前
    4.一般最多設(shè)置為6;
    5.將最大操作數(shù)的值設(shè)置為1,可以實現(xiàn)任務的串行效果,但是要注意的是,并不是只開一條子線程(通常會開兩條子線程,循環(huán)回收復用)
    6.如果設(shè)置為0,表示 任何任務都不會執(zhí)行
    7.如果一組任務是按順序執(zhí)行的,就是串行隊
    使用方法
//表示同一時間內(nèi)最多執(zhí)行2各任務,并且是并發(fā)執(zhí)行
queue.maxConcurrentOperationCount=2;
  • NSOperation常用的方法
    • 隊列的掛起(也稱暫停)
      作用:暫停隊列中的任務
      任務的狀態(tài):
      隊列中的任務是有狀態(tài)的(如執(zhí)行狀態(tài),和就緒狀態(tài)),而且當前正在處于執(zhí)行狀態(tài)的任務是不能夠暫停的,只能暫停就緒的任務
      暫停
示例:
-(IBAction)pauseBtn:(id)sender { 
//暫停當前隊列中的操作,停止執(zhí)行    
[self.queue setSuspended:YES];
}

恢復(暫停的逆設(shè)置)

-(IBAction)resumBtn:(id)sender {    
//回復當前隊列中的操作,繼續(xù)執(zhí)行    
[self.queue setSuspended:NO];
}

注意:
1.并不能立刻暫停當前執(zhí)行的任務
2.當前正在執(zhí)行的任務是不能暫停的,暫停的是等待的任務

  • 隊列的取消
-(IBAction)cancellBtn:(id)sender {    
[self.queue cancelAllOperations];
}

注意
0.暫停和取消操作不能作用于當前正在執(zhí)行的任務,只能作用在隊列中就緒執(zhí)行的任務
1.取消是取消隊列中的所有任務,除了正在執(zhí)行的任務
2.一旦被取消,就不能回復之前的操作
3.調(diào)用了cancelAllOperations方法的話,cancelled屬性的值也會跟隨改變,由no變?yōu)閥es 或又yes改變?yōu)閚o

  • ****自定義****Operation****類的掛起取消****
    注意:當自定義一個操作,點擊取消后,任務不會結(jié)束
    如何實現(xiàn)自定義Operation類的掛起取消:
    在自定義的main方法內(nèi)判斷calcelled屬性的真假,因為當外界執(zhí)行了cancelAllOperations方法后,cancelled屬性的值就會發(fā)生改變,變?yōu)閥es
-(void)main
{    
for (int i = 0; i <1000; i++) {        
NSLog(@"1-------%d--------%@",i,[NSThread currentThread]);    
}    
for (int i = 0; i <1000; i++) {        
NSLog(@"2-------%d--------%@",i,[NSThread currentThread]);
    }
    if (self.cancelled) {//判斷外界是否執(zhí)行了cancelAllOperations操作
        return;
    }

如何快速結(jié)束任務:
可以將判斷放到耗時操作內(nèi)(上邊的程序就是指for循環(huán)內(nèi)),但不推薦這么做,因為判斷操作也非常耗費性能
**蘋果官方給的建議 : **
自定義的NSOperation可以在每一段耗時操作之后都去判斷一下cancel屬性是否為真

  • 操作的依賴和監(jiān)聽
    • 操作依賴:
      基本介紹:想要讓一個操作在另一個操作執(zhí)行完畢的時候再執(zhí)行,可以使用操作依賴來完成
      使用方法:addDependencing
//設(shè)置依賴,也就是設(shè)置操作的執(zhí)行順序
    [op1 addDependency:op2]; // op1 依賴 op2
    [op2 addDependency:op3]; // op2 依賴 op3
    [op3 addDependency:op4]; // op3 依賴 op4

**注意點 : **
1.操作依賴必須在添加到隊列之前來進行設(shè)置
2.操作依賴可以跨隊列依賴,很強大
操作依賴與死鎖:
如果設(shè)置了循環(huán)依賴會發(fā)生死鎖,也就是說與循環(huán)依賴有關(guān)系的所有操作都不會執(zhí)行

//!!!!不能設(shè)置循環(huán)依賴(死鎖--op1&op2 不會執(zhí)行)
[op2 addDependency:op1];
[op1 addDependency:op2];
  • **操作監(jiān)聽 : **(一個操作結(jié)束之后給我們發(fā)送一條消息)
    使用方法:op1.completionBlock{},也就是說當op1結(jié)束之后會自動調(diào)用block中的代碼塊
    //completionBlock是一個屬性,既可以通過點語法設(shè)置,也可以通過set方法設(shè)置
    op1.completionBlock = ^ {
        NSLog(@"op1已經(jīng)執(zhí)行完畢");
    };
    [op1 setCompletionBlock:^{
        NSLog(@"通過setCompletionBlock方法實現(xiàn)對op1的監(jiān)聽");
    }];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子瞄沙,更是在濱河造成了極大的恐慌墨坚,老刑警劉巖欲鹏,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件暴凑,死亡現(xiàn)場離奇詭異如绸,居然都是意外死亡完域,警方通過查閱死者的電腦和手機软吐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吟税,“玉大人凹耙,你說我怎么就攤上這事姿现。” “怎么了肖抱?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵备典,是天一觀的道長。 經(jīng)常有香客問我意述,道長提佣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任荤崇,我火速辦了婚禮拌屏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘天试。我一直安慰自己槐壳,他們只是感情好,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布喜每。 她就那樣靜靜地躺著务唐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪带兜。 梳的紋絲不亂的頭發(fā)上枫笛,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機與錄音刚照,去河邊找鬼刑巧。 笑死,一個胖子當著我的面吹牛无畔,可吹牛的內(nèi)容都是我干的啊楚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼浑彰,長吁一口氣:“原來是場噩夢啊……” “哼恭理!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起郭变,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤颜价,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后诉濒,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體周伦,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年未荒,在試婚紗的時候發(fā)現(xiàn)自己被綠了专挪。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖狈蚤,靈堂內(nèi)的尸體忽然破棺而出困肩,到底是詐尸還是另有隱情,我是刑警寧澤脆侮,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站勇劣,受9級特大地震影響靖避,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜比默,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一幻捏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧命咐,春花似錦篡九、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至窜司,卻和暖如春沛善,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背塞祈。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工金刁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人议薪。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓尤蛮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親斯议。 傳聞我的和親對象是個殘疾皇子产捞,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

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