多線程N(yùn)SOperation

NSOperation的作用:

配合使用NSOperation和NSOperationQueue能實(shí)現(xiàn)多線程編程.

NSOperation和NSOperationQueue能實(shí)現(xiàn)多線程的具體步驟

1.首先需要將執(zhí)行的操作封裝到一個(gè)NSOperation對(duì)象中(我們稱之為 任務(wù))
2.然后將NSOperation對(duì)象加到NSOperationQueue中
3.系統(tǒng)會(huì)自動(dòng)將NSOperationQueue中的NSOperation取出來(lái)
4.將取出的NSOperation封裝的操作放在一條新線程中執(zhí)行

NSOperation的子類

1.NSOperation是一個(gè)抽象類,不具備封裝操作的能力,必須使用它的子類
2.使用NSOperation子類的方式有3種
1>NSInvocationOperation
2>NSBlockOperation
自定義子類繼承NSOperation,實(shí)現(xiàn)內(nèi)部相應(yīng)的方法

雖然NSOperation較GCD比較而言,有點(diǎn)繁瑣,但是它能夠自由的控制任務(wù)的執(zhí)行,而且經(jīng)過(guò)測(cè)試,它的穩(wěn)定性比較高.

好了現(xiàn)在介紹:自定義NSOperation的方式來(lái)添加任務(wù)

自定義類,繼承于NSOperation

// NSOperation內(nèi)部有這個(gè)方法, 是用來(lái)專門(mén),封裝任務(wù)體的
// 默認(rèn)情況下如果直接調(diào)用start的時(shí)候,不會(huì)新開(kāi)一條新線程去執(zhí)行操作
- (void)main
{
    [NSThread sleepForTimeInterval:1.0];
    NSLog(@"我愛(ài)你 ------ %@", [NSThread currentThread]);

}

利用NSInvocationOperation來(lái)添加任務(wù)

1.創(chuàng)建NSInvocationOperation對(duì)象

NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run:) object:@"我愛(ài)你"];

2.調(diào)用start方法開(kāi)始執(zhí)行操作

  • (void)start
    一點(diǎn)執(zhí)行這個(gè)操作,就會(huì)調(diào)用target的sel的方法
    3.注意
    1>默認(rèn)情況下,調(diào)用了start方法后并不會(huì)開(kāi)一條新線程去執(zhí)行操作,而是在當(dāng)前線程同步執(zhí)行操作
    2>只有將NSOperation放在一個(gè)NSOperationQueue中,才會(huì)異步執(zhí)行操作

利用NSBlockOperation來(lái)添加任務(wù)

1.創(chuàng)建NSBlockOperation對(duì)象
2.通過(guò)addExecutionBlock:方法添加更多的操作
3.注意:只要NSBlockOperation封裝的操作數(shù) > 1,就會(huì)異步執(zhí)行操作

// block 直接將 操作封裝在 block中   ,執(zhí)行的毛嫉。  會(huì)進(jìn)行并行操作裳仆,并且第一條操作  安排在主線程。 不必指定 target
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"?(′???`?)----%@",[NSThread currentThread]);
    }];
    [operation addExecutionBlock:^{
        NSLog(@"我愛(ài)你----%@",[NSThread currentThread]);;
    }];
    [operation addExecutionBlock:^{
        NSLog(@"我愛(ài)你----%@",[NSThread currentThread]);;
    }];
    [operation addExecutionBlock:^{
        NSLog(@"我愛(ài)你----%@",[NSThread currentThread]);;
    }];
    // 調(diào)用  start 統(tǒng)一開(kāi)始執(zhí)行任務(wù)
    [operation start];

控制臺(tái)輸出:


Snip20150927_2.png

NSOperationQueue

NSOperationQueue的作用

1.NSOperation可以調(diào)用start方法來(lái)執(zhí)行任務(wù),但默認(rèn)是同步執(zhí)行的
2.如果將NSOperation添加到NSOperationQueue(操作隊(duì)列)中,系統(tǒng)會(huì)自動(dòng)異步執(zhí)行NSOperation中的操作

添加操作(任務(wù))到NSOperationQueue中 (需要注意的是,一旦加入隊(duì)列,任務(wù)就會(huì)被執(zhí)行.)

1.添加任務(wù)對(duì)象到隊(duì)列中
- (void)addOperation:(NSOperation *)op
2.添加任務(wù)'block'到隊(duì)列,直接執(zhí)行
- (void)addOperationWithBlock:(void (^)(void))block

// 創(chuàng)建隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//
__block UIImage *image1;
    NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
        [NSThread sleepForTimeInterval:2.0];
        NSURL *url = [NSURL URLWithString:@"http://fc.topit.me/c/4f/99/11922014783d4994fco.jpg"]; 
        NSData *data = [NSData dataWithContentsOfURL:url];
        image1 = [UIImage imageWithData:data];
        NSLog(@"1------%@",[NSThread currentThread]);
        
    }];
    __block UIImage *image2;
    NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{
        [NSThread sleepForTimeInterval:2.0];
        NSURL *url = [NSURL URLWithString:@"http://cdn.duitang.com/uploads/item/201311/25/20131125164036_NUAC8.jpeg"];
        
        NSData *data = [NSData dataWithContentsOfURL:url];
        image2 = [UIImage imageWithData:data];
        NSLog(@"2------%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *block3 = [NSBlockOperation blockOperationWithBlock:^{
        UIGraphicsBeginImageContext(CGSizeMake(200, 200));
        
        [image1 drawInRect:CGRectMake(0, 50, 200, 150)];
        [image2 drawInRect:CGRectMake(0, 0, 200, 50)];
        
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        
        UIGraphicsEndImageContext();
        
        // 回到主隊(duì)列  裹纳, 進(jìn)行UI賦值
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.imageView.image = image;
        }];
        
        
    }];
    
    // addDependency   添加依賴  ,  前倆個(gè)  紧武,執(zhí)行完了之后  最后一個(gè)再執(zhí)行剃氧。
    [block3 addDependency:block1];
    [block3 addDependency:block2];
    
    [queue addOperation:block1];
    [queue addOperation:block2];
    [  queue addOperation:block3 ];
    
    
    
//    // 先讓執(zhí)行 block1, block2 (異步并發(fā)執(zhí)行) 阻星,在進(jìn)行  block3 的執(zhí)行
//    [queue addOperations:@[block1,block2] waitUntilFinished:YES];
//    [queue addOperation:block3];
//    

幾種常見(jiàn)的屬性和方法

1.最大并發(fā)數(shù)(同時(shí)執(zhí)行的任務(wù)數(shù)) 最大并發(fā)數(shù)一般都是系統(tǒng)給出,我任務(wù),系統(tǒng)并發(fā)送是系統(tǒng)根據(jù)它的性能, 給分配的線程,如果性能高,可能多分點(diǎn). 至于并發(fā)送內(nèi)部怎么執(zhí)行 ,系統(tǒng)自行做決定, 它認(rèn)為哪條線程空閑,他就會(huì)把哪條線程交給你

- (NSInteger)maxCurrentOperationCount;
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt

有些人,會(huì)陷入誤區(qū), 如果設(shè)置了最大并發(fā)數(shù)是1,那么系統(tǒng)就只會(huì)創(chuàng)建一條線程, 因?yàn)?同一時(shí)間只允許一條線程執(zhí)行任務(wù), 但是這種想法是錯(cuò)誤的, 系統(tǒng)只是保持同一時(shí)間執(zhí)行任務(wù)是一條線程, 但沒(méi)表示 換個(gè)時(shí)間就不能換線程

// 默認(rèn)不設(shè)置并發(fā)數(shù)的時(shí)候, 異步執(zhí)行, 創(chuàng)建多條線程
let queue = NSOperationQueue()
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }

Snip20150928_2.png

***添加queue.maxConcurrentOperationCount = 1
Snip20150928_3.png

可以看出來(lái), 線程并不是一樣的. 所以最大并發(fā)數(shù)的理解, 應(yīng)該是我上面指出的

2.隊(duì)列的取消,暫停,和恢復(fù)
1>取消隊(duì)列的所有操作
- (void)cancelAllOpertions
注意: 也可以調(diào)用NSOperation的-(void)cancel方法取消單個(gè)操作. (總感覺(jué)單個(gè)任務(wù)取消不掉)
2>暫停和恢復(fù)隊(duì)列
- (void)setSuspended:(BOOL)b// YES 代表暫停隊(duì)列,NO代表恢復(fù)隊(duì)列
- (BOOL)isSuspended

操作依賴

首先依賴其他的線程中也有說(shuō)過(guò) GCD ----<barrier, group都是依賴的意思>
NSOperation之間可以設(shè)置依賴來(lái)保證執(zhí)行順序.
操作之間添加依賴
[operationB addDependency:operationA] 操作B依賴于A
不同隊(duì)列之間也可以進(jìn)行任務(wù)的依賴, 但是需要注意的是, 不要相互依賴

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末朋鞍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌滥酥,老刑警劉巖更舞,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異恨狈,居然都是意外死亡疏哗,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)禾怠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)返奉,“玉大人,你說(shuō)我怎么就攤上這事吗氏⊙科” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵弦讽,是天一觀的道長(zhǎng)污尉。 經(jīng)常有香客問(wèn)我,道長(zhǎng)往产,這世上最難降的妖魔是什么被碗? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮仿村,結(jié)果婚禮上锐朴,老公的妹妹穿的比我還像新娘。我一直安慰自己蔼囊,他們只是感情好焚志,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著畏鼓,像睡著了一般酱酬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上云矫,一...
    開(kāi)封第一講書(shū)人閱讀 51,482評(píng)論 1 302
  • 那天膳沽,我揣著相機(jī)與錄音,去河邊找鬼让禀。 笑死贵少,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的堆缘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼普碎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼吼肥!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤缀皱,失蹤者是張志新(化名)和其女友劉穎斗这,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體啤斗,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡表箭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了钮莲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片免钻。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖崔拥,靈堂內(nèi)的尸體忽然破棺而出极舔,到底是詐尸還是另有隱情,我是刑警寧澤链瓦,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布拆魏,位于F島的核電站,受9級(jí)特大地震影響慈俯,放射性物質(zhì)發(fā)生泄漏渤刃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一贴膘、第九天 我趴在偏房一處隱蔽的房頂上張望卖子。 院中可真熱鬧,春花似錦步鉴、人聲如沸揪胃。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)喊递。三九已至,卻和暖如春阳似,著一層夾襖步出監(jiān)牢的瞬間骚勘,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工撮奏, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留俏讹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓畜吊,卻偏偏與公主長(zhǎng)得像泽疆,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子玲献,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

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