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
- 創(chuàng)建一個 Operation 后,需要調(diào)用start
//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];
線程同步
- 線程同步就是為了防止多個線程搶奪同一個資源造成的數(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