iOS多線程NSThread,GCD ,NSOperation

NSThread:

這套方案是經(jīng)過蘋果封裝后的数苫,并且完全面向?qū)ο蟮摹K阅憧梢灾苯硬倏鼐€程對象知残,非常直觀和方便。但是比庄,它的生命周期還是需要我們手動管理求妹,所以這套方案也是偶爾用用,比如 [NSThread currentThread]佳窑,它可以獲取當(dāng)前線程類制恍,你就可以知道當(dāng)前線程的各種屬性,用于調(diào)試十分方便神凑。下面來看看它的一些用法净神。

  • 創(chuàng)建并啟動
    -先創(chuàng)建線程類,再啟動
// 創(chuàng)建 
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:nil]; 
// 啟動
[thread start];
  • 創(chuàng)建并自動啟動
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:nil];
  • 使用 NSObject 的方法創(chuàng)建并自動啟動
[self performSelectorInBackground:@selector(run:) withObject:nil];

GCD

Grand Central Dispatch溉委,它是蘋果為多核的并行運算提出的解決方案鹃唯,所以會自動合理地利用更多的CPU內(nèi)核(比如雙核、四核)瓣喊,最重要的是它會自動管理線程的生命周期(創(chuàng)建線程坡慌、調(diào)度任務(wù)、銷毀線程)型宝,完全不需要我們管理八匠,我們只需要告訴干什么就行。同時它使用的也是 c語言趴酣,不過由于使用了 Block(Swift里叫做閉包)梨树,使得使用起來更加方便,而且靈活岖寞。

  • 任務(wù)和隊列

  • 在 GCD中抡四,加入了兩個非常重要的概念: 任務(wù)隊列
    任務(wù):即操作仗谆,你想要干什么指巡,說白了就是一段代碼,在 GCD 中就是一個 Block隶垮,所以添加任務(wù)十分方便藻雪。任務(wù)有兩種執(zhí)行方式: 同步執(zhí)行異步執(zhí)行,他們之間的區(qū)別是 是否會創(chuàng)建新的線程狸吞。

  • 同步(sync) 和 異步(async) 的主要區(qū)別在于會不會阻塞當(dāng)前線程勉耀,直到 Block 中的任務(wù)執(zhí)行完畢指煎!
    如果是 同步(sync) 操作,它會阻塞當(dāng)前線程并等待 Block 中的任務(wù)執(zhí)行完畢便斥,然后當(dāng)前線程才會繼續(xù)往下運行至壤。
    如果是 異步(async)操作,當(dāng)前線程會直接往下執(zhí)行枢纠,它不會阻塞當(dāng)前線程像街。

  • 隊列:用于存放任務(wù)。一共有兩種隊列晋渺, 串行隊列并行隊列镰绎。

  • 串行隊列 中的任務(wù)會根據(jù)隊列的定義 FIFO 的執(zhí)行,一個進來執(zhí)行完出去木西,下一個才會進來跟狱。

  • 并行隊列 根據(jù)隊列的定義 FIFO 的執(zhí)行,但它取出來一個就會放到別的線程户魏,然后再取出來一個又放到另一個的線程驶臊。這樣由于取的動作很快,忽略不計叼丑,看起來关翎,所有的任務(wù)都是一起執(zhí)行的。不過需要注意鸠信,GCD 會根據(jù)系統(tǒng)資源控制并行的數(shù)量纵寝,所以如果任務(wù)很多,它并不會讓所有任務(wù)同時執(zhí)行星立。

  • 創(chuàng)建隊列
    主隊列:這是一個特殊的 串行隊列
    它用于刷新 UI爽茴,任何需要刷新 UI 的工作都要在主隊列執(zhí)行,所以一般耗時的任務(wù)都要放到別的線程執(zhí)行绰垂。
    自己創(chuàng)建的隊列:~~凡是自己創(chuàng)建的隊列都是 串行隊列
    室奏。其中第一個參數(shù)是標(biāo)識符,用于 DEBUG 的時候標(biāo)識唯一的隊列劲装,可以為空胧沫。大家可以看xcode的文檔查看參數(shù)意義。

  • 第二個參數(shù)用來表示創(chuàng)建的隊列是串行的還是并行的占业,傳入 DISPATCH_QUEUE_SERIAL 或 NULL表示創(chuàng)建串行隊列绒怨。
    傳入 DISPATCH_QUEUE_CONCURRENT表示創(chuàng)建并行隊列。

NSOperation和NSOperationQueue

  • NSOperation 是蘋果公司對 GCD 的封裝谦疾,完全面向?qū)ο竽硝澹允褂闷饋砀美斫狻?大家可以看到 NSOperation 和 NSOperationQueue 分別對應(yīng) GCD 的 任務(wù) 和 隊列 。操作步驟也很好理解:
  • 將要執(zhí)行的任務(wù)封裝到一個 NSOperation 對象中念恍。
  • 將此任務(wù)添加到一個 NSOperationQueue 對象中六剥。
添加任務(wù)
  • NSOperation
    只是一個抽象類佑附,所以不能封裝任務(wù)。但它有 2 個子類用于封裝任務(wù)仗考。分別是:NSInvocationOperation和NSBlockOperation
    • 創(chuàng)建一個 Operation 后,需要調(diào)用start
      方法來啟動任務(wù)词爬,它會 默認(rèn)在當(dāng)前隊列同步執(zhí)行秃嗜。當(dāng)然你也可以在中途取消一個任務(wù),只需要調(diào)用其cancel
//1.創(chuàng)建NSInvocationOperation對象 
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil]; //2.開始執(zhí)行
 [operation start];
//1.創(chuàng)建NSBlockOperation對象 NSBlockOperation
 *operation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"%@", [NSThread currentThread]); }]; 
//2.開始任務(wù) 
operation start];

線程同步

  1. 線程同步就是為了防止多個線程搶奪同一個資源造成的數(shù)據(jù)安全問題顿膨,所采取的一種措施
    • 互斥鎖 :給需要同步的代碼塊加一個互斥鎖锅锨,就可以保證每次只有一個線程訪問此代碼塊。
@synchronized(self) { //需要執(zhí)行的代碼塊}
 - **同步執(zhí)行** :我們可以使用多線程的知識恋沃,把多個線程都要執(zhí)行此段代碼添加到同一個串行隊列必搞,這樣就實現(xiàn)了線程同步的概念。當(dāng)然這里可以使用 GCD和 NSOperation 兩種方案囊咏,我都寫出來恕洲。
//GCD 
//需要一個全局變量queue,要讓所有線程的這個操作都加到一個queue中 
dispatch_sync(queue, ^{ 
NSInteger ticket = lastTicket;
 [NSThread sleepForTimeInterval:0.1];
 NSLog(@"%ld - %@",ticket, [NSThread currentThread]);
 ticket -= 1; lastTicket = ticket; 
}); 
//NSOperation & NSOperationQueue 
//重點:1. 全局的 NSOperationQueue, 所有的操作添加到同一個queue中 
// 2. 設(shè)置 queue 的 maxConcurrentOperationCount 為 1 
// 3. 如果后續(xù)操作需要Block中的結(jié)果梅割,就需要調(diào)用每個操作的waitUntilFinished霜第,阻塞當(dāng)前線程,一直等到當(dāng)前操作完成户辞,才允許執(zhí)行后面的泌类。waitUntilFinished 要在添加到隊列之后! NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ 
NSInteger ticket = lastTicket; 
[NSThread sleepForTimeInterval:1]; 
NSLog(@"%ld - %@",ticket, [NSThread currentThread]); 
ticket -= 1; lastTicket = ticket; }];
 [queue addOperation:operation];
 [operation waitUntilFinished]; //后續(xù)要做的事

延遲執(zhí)行

延遲執(zhí)行就是延時一段時間再執(zhí)行某段代碼底燎。下面說一些常用方法刃榨。
perform

// 3秒后自動調(diào)用self的run:方法,并且傳遞參數(shù):@"abc"
 [self performSelector:@selector(run:) withObject:@"abc" afterDelay:3];

GCD

// 創(chuàng)建隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 設(shè)置延時双仍,單位秒
double delay = 3; 
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), queue, ^{ 
// 3秒后需要執(zhí)行的任務(wù)
});

NSTimer

[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(run:) userInfo:@"abc" repeats:NO];

單例模式

@interface Tool : NSObject <NSCopying>
+(instancetype)sharedTool;
@end
@implementation Toolstatic id _instance;
+(instancetype)sharedTool
 { static dispatch_once_t onceToken; 
  dispatch_once(&onceToken, ^{
 _instance = [[Tool alloc] init]; 
}); 
return _instance;
}
@end

從其他線程回到主線程的方法

NSThread

//Objective-C
[self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:NO];

GCD

dispatch_async(dispatch_get_main_queue(), ^{
});

NSOperationQueue

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
}];

轉(zhuǎn)載于http://www.reibang.com/p/0b0d9b1f1f19

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末枢希,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子朱沃,更是在濱河造成了極大的恐慌晴玖,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件为流,死亡現(xiàn)場離奇詭異呕屎,居然都是意外死亡,警方通過查閱死者的電腦和手機敬察,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門秀睛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人莲祸,你說我怎么就攤上這事蹂安⊥钟” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵田盈,是天一觀的道長畜号。 經(jīng)常有香客問我,道長允瞧,這世上最難降的妖魔是什么简软? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮述暂,結(jié)果婚禮上痹升,老公的妹妹穿的比我還像新娘。我一直安慰自己畦韭,他們只是感情好疼蛾,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著艺配,像睡著了一般察郁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上转唉,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天绳锅,我揣著相機與錄音,去河邊找鬼酝掩。 笑死鳞芙,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的期虾。 我是一名探鬼主播原朝,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼镶苞!你這毒婦竟也來了喳坠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤茂蚓,失蹤者是張志新(化名)和其女友劉穎壕鹉,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體聋涨,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡晾浴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了牍白。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脊凰。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖茂腥,靈堂內(nèi)的尸體忽然破棺而出狸涌,到底是詐尸還是另有隱情切省,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布帕胆,位于F島的核電站朝捆,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏懒豹。R本人自食惡果不足惜芙盘,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望歼捐。 院中可真熱鬧,春花似錦晨汹、人聲如沸豹储。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽剥扣。三九已至,卻和暖如春铝穷,著一層夾襖步出監(jiān)牢的瞬間钠怯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乙墙。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓渡讼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親剥懒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

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