iOS多線程有四套多線程方案:
- Pthreads
- NSThread
- GCD
- NSOperation & NSOperationQueue
接下來(lái)我來(lái)一個(gè)一個(gè)介紹他們
Pthreads
在類Unix操作系統(tǒng)(Unix渡蜻、Linux它浅、Mac OS X等)中脚曾,都使用Pthreads作為操作系統(tǒng)的線程闽瓢。
這套多線程是使用C語(yǔ)言實(shí)現(xiàn)的,所以可移植性很高蕊玷。但是在實(shí)際項(xiàng)目中基本上不會(huì)用到邮利,這里只做簡(jiǎn)單的介紹。
首先要包含頭文件pthread.h
void *star(void *data)
{
NSLog(@"%@",[NSThread currentThread]);
return NULL;
}
- (IBAction)buttonTouch:(id)sender
{
pthread_t thread;
pthread_create(&thread, NULL, star, NULL);
}
控制臺(tái)輸出:
2016-09-07 14:37:44.734 GCDDemo[2660:1124576] <NSThread: 0x7fd2024a58a0>{number = 2, name = (null)}
NSThread
NSThread是蘋果封裝的面向?qū)ο筇幚矶嗑€程的方案集畅。但是他卻不夠智能近弟,需要我們手動(dòng)的管理線程的生命周期以及同步缅糟。所以這套方案我們通常也不常用挺智。
創(chuàng)建線程:
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(thisThread) object:nil];
[thread start];
或者使用類方法
[NSThread detachNewThreadSelector:@selector(thisThread) toTarget:self withObject:nil];
或者使用NSObject的類方法:
[self performSelector:@selector(thisThread)];
但是NSThread需要使用NSLock來(lái)給線程上鎖。以及進(jìn)行其他操作窗宦,它不夠智能赦颇。所以我們只在很少的情況使用它
GCD
GCD全稱Grand Central Dispatch。是蘋果提出的多核并行運(yùn)算的解決方案赴涵。也就是說(shuō)他會(huì)自動(dòng)利用多核CPU媒怯,它會(huì)自動(dòng)管理線程的生命周期。只需要我們告訴他應(yīng)該做什么髓窜。
在GCD中有兩個(gè)概念扇苞,一個(gè)是任務(wù),一個(gè)是隊(duì)列:
- 任務(wù)就是一串代碼寄纵,在GCD中使用的Block鳖敷。只需要將需要做的事情添加到Block里面就行了。任務(wù)有兩種執(zhí)行方式同步或者異步:
- 同步執(zhí)行:會(huì)一直阻塞當(dāng)前線程直到任務(wù)處理完程拭。
- 異步執(zhí)行:不會(huì)阻塞當(dāng)前線程定踱。當(dāng)前線程會(huì)直接往下處理,直到該任務(wù)作出反應(yīng)恃鞋。
- 隊(duì)列可以理解為用于存放任務(wù)的容器崖媚,隊(duì)列分為串行隊(duì)列和并行隊(duì)列兩種
- 串行隊(duì)列:放在串行隊(duì)列中的任務(wù)會(huì)遵循先入先出的原則,在當(dāng)前線程中一個(gè)一個(gè)按順序執(zhí)行恤浪。
- 并行隊(duì)列:放在并行隊(duì)列中的任務(wù)雖然也會(huì)遵循先入先出的原則畅哑,但是會(huì)開不同的線程讓他們同時(shí)執(zhí)行。不過(guò)同時(shí)執(zhí)行的數(shù)量也會(huì)受到系統(tǒng)資源的限制水由。
創(chuàng)建隊(duì)列
- 主隊(duì)列:主隊(duì)列是一條串行隊(duì)列荠呐,用于刷新UI。
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"%@",queue);
控制臺(tái)輸出
2016-09-08 14:15:25.361 GCDDemo[6984:2309204] <OS_dispatch_queue: com.apple.main-thread[0x10c34e9c0]>
- 用戶的隊(duì)列:用戶可以自己創(chuàng)建串行隊(duì)列或者并行隊(duì)列。
dispatch_queue_t queue = dispatch_queue_create("wodeduilie", NULL);
NSLog(@"%@",queue);
這個(gè)函數(shù)有兩個(gè)參數(shù)直秆,一個(gè)是隊(duì)列名濒募,第二個(gè)參數(shù)控制是否為串行或者并行。第二個(gè)參數(shù)傳入DISPATCH_QUEUE_SERIAL或者NULL表示串行圾结。DISPATCH_QUEUE_CONCURRENT表示并行瑰剃。
創(chuàng)建任務(wù)
- 同步任務(wù):會(huì)阻塞當(dāng)前進(jìn)程
dispatch_queue_t queue = dispatch_queue_create("wodeduilie", NULL);
dispatch_sync(queue, ^{
NSLog(@"%@",[NSThread currentThread]);
});
- 異步任務(wù):不會(huì)阻塞當(dāng)前線程
dispatch_queue_t queue = dispatch_queue_create("wodeduilie", NULL);
dispatch_async(queue, ^{
NSLog(@"%@",[NSThread currentThread]);
});
NSOperation & NSOperationQueue
NSOperation是面向?qū)ο蟮模菍?duì)GCD的封裝筝野。NSOperation和 NSOperationQueue分別對(duì)應(yīng)GCD的任務(wù)和隊(duì)列
創(chuàng)建任務(wù)
NSOperation是抽象類晌姚,如果你想使用它需要使用它的子類:
- NSInvocationOperation通過(guò)綁定方法來(lái)封裝任務(wù):
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(thisThread) object:nil];
[operation start];
- NSBlockOperation通過(guò)Block來(lái)封裝任務(wù):
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@",[NSThread currentThread]);
}];
[operation start];
NSBlockOperation中還有一個(gè)方法addExecutionBlock:
來(lái)添加多個(gè)任務(wù),而且這些任務(wù)是并發(fā)執(zhí)行的
控制臺(tái)輸出:
2016-09-08 22:21:26.660 GCDDemo[8112:2598032] <NSThread: 0x7fd151607d20>{number = 1, name = main}
你需要使用start方法或者cancel方法來(lái)開始或者取消一個(gè)任務(wù)歇竟。
創(chuàng)建隊(duì)列
在NSOperationQueue中只有兩種隊(duì)列挥唠,一個(gè)是主隊(duì)列,一個(gè)是自己創(chuàng)建的其他隊(duì)列:
- 主隊(duì)列就是我們用于刷新UI的:
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@",[NSThread currentThread]);
}];
NSOperationQueue *queue = [NSOperationQueue mainQueue];
[queue addOperation:operation];
控制臺(tái)輸出:
2016-09-08 22:36:33.053 GCDDemo[8279:2611844] <NSThread: 0x7f828b6020c0>{number = 1, name = main}
- 其他隊(duì)列就是用于我們進(jìn)行耗時(shí)操作的隊(duì)列:
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@",[NSThread currentThread]);
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
控制臺(tái)輸出:
2016-09-08 22:40:49.459 GCDDemo[8405:2616956] <NSThread: 0x7f8833e2fd30>{number = 2, name = (null)}
我們使用自定義的隊(duì)列的時(shí)候焕议,加入該隊(duì)列的任務(wù)會(huì)自動(dòng)的并發(fā)執(zhí)行宝磨。但是有一個(gè)參數(shù)表示最大并發(fā)執(zhí)行的數(shù)量maxConcurrentOperationCount。
當(dāng)我們將這個(gè)參數(shù)設(shè)為1時(shí)就是串行隊(duì)列盅安。
在NSOperationQueue中我們還可以直接使用方法添加任務(wù)
- (void)addOperationWithBlock:(void (^)(void))block;
只要我們將任務(wù)添加到隊(duì)列中就會(huì)自動(dòng)執(zhí)行任務(wù)的start方法唤锉。