寫(xiě)此文章是為了能夠加深自己的記憶,并且對(duì)技術(shù)點(diǎn)有個(gè)記錄,方便查閱
這篇文章主要寫(xiě)一些iOS多線程的操作
1.NSThread([θred], 英式發(fā)音):輕量級(jí)的,編程中很少用,需要自己管理線程,加鎖等,很復(fù)雜,所以平時(shí)編程很少用。
比較常用的是獲取當(dāng)前線程和暫停當(dāng)前線程
- (void)textAction {
NSThread *current = [NSThread currentThread];
NSLog(@"current:%@",current);
[NSThread sleepForTimeInterval:2];
NSLog(@"finish");
}
2.引自百度百科
Grand Central Dispatch(GCD) 是 Apple 開(kāi)發(fā)的一個(gè)多核編程的較新的解決方法。它主要用于優(yōu)化應(yīng)用程序以支持多核處理器以及其他對(duì)稱多處理系統(tǒng)。它是一個(gè)在線程池模式的基礎(chǔ)上執(zhí)行的并發(fā)任務(wù)。在 Mac OS X 10.6 雪豹中首次推出,也可在 iOS 4 及以上版本使用。
GCD有一套完整的api,使用方便,也應(yīng)該是在實(shí)際開(kāi)發(fā)中用的最多的
GCD中有同步(sync)和異步之分(async),串行和并行隊(duì)列之分
串行隊(duì)列(Serial Dispatch Queue):
并行隊(duì)列(Concurrent Dispatch Queue):
GCD自帶的兩個(gè)隊(duì)列:
//主線程,串行
dispatch_queue_t mainQueue = dispatch_get_main_queue();
//全局隊(duì)列,并行
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//自定義串行
dispatch_queue_t serialQueue = dispatch_queue_create("com.kevin.abcd", DISPATCH_QUEUE_SERIAL);
//自定義并行
dispatch_queue_t concurrentQueue =dispatch_queue_create("com.kevin.efgh", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue;
//異步,會(huì)開(kāi)啟新線程
dispatch_async(queue, ^{
//
});
//同步,不會(huì)開(kāi)啟新線程
dispatch_sync(queue, ^{
//
});
用的比較多的其實(shí)是主線程刷新ui
dispatch_async(dispatch_get_main_queue(), ^{
//
});
還有任務(wù)組,比如需要把兩個(gè)請(qǐng)求的結(jié)果合并為一個(gè),那么可以是兩個(gè)異步的請(qǐng)求加入dispatch group,等待兩個(gè)都返回后,調(diào)用group的通知,會(huì)告知我們?nèi)蝿?wù)組里的任務(wù)都完成了
dispatch_queue_t concurrentQueue =dispatch_queue_create("com.kevin.efgh", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, concurrentQueue, ^{
//執(zhí)行第一個(gè)任務(wù)
});
dispatch_group_async(group, concurrentQueue, ^{
//執(zhí)行第二個(gè)任務(wù)
});
dispatch_group_notify(group, concurrentQueue, ^{
//group 中的任務(wù)執(zhí)行完
});
另外需要注意的是在dispatch_group_async中如果執(zhí)行的是異步操作的話,則notify會(huì)失效,需要用
//確保配對(duì)使用
dispatch_group_enter(group);
dispatch_group_leave(group);
gcd還有許多平常我們經(jīng)常用的的,例如單利的創(chuàng)建
+(instancetype)sharedInstance \
{ \
static CLASS * sharedInstance = nil; \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
sharedInstance = [[CLASS alloc] init]; \
}); \
return sharedInstance; \
}
有時(shí)我們需要延遲執(zhí)行一些操作
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// code to be executed after a specified delay
});
如果需要執(zhí)行兩組任務(wù),第一組必須在第二組之前運(yùn)行,則可以用柵欄函數(shù)解決
dispatch_queue_t concurrentQueueTwo = dispatch_queue_create("com.kevin.concue=rrent", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
NSLog(@"1");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"2");
});
dispatch_barrier_async(concurrentQueue, ^{
NSLog(@"barrier");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"3");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"4");
});
gcd還提供線程等待的方法,dispatch_group_wait
gcd中的信號(hào)量semaphore([?sem?f?:(r)])
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);//創(chuàng)建總數(shù)為0的信號(hào)
dispatch_semaphore_signal(semaphore);//發(fā)送信號(hào),信號(hào)+1
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//等待信號(hào),當(dāng)信號(hào)量少于0時(shí)就會(huì)一直等待,否則正常執(zhí)行,并使信號(hào)量-1
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);//創(chuàng)建總數(shù)為0的信號(hào)
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"1:%@",[NSThread currentThread]);
// dispatch_semaphore_signal(semaphore);//發(fā)送信號(hào),信號(hào)+1
});
// dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//等待信號(hào),當(dāng)信號(hào)量少于0時(shí)就會(huì)一直等待,否則正常執(zhí)行,并使信號(hào)量-1
NSLog(@"5");
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"2:%@",[NSThread currentThread]);
// dispatch_semaphore_signal(semaphore);//發(fā)送信號(hào),信號(hào)+1
});
NSLog(@"6");
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"3:%@",[NSThread currentThread]);
// dispatch_semaphore_signal(semaphore);//+1
});
NSLog(@"7");
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"4:%@",[NSThread currentThread]);
// dispatch_semaphore_signal(semaphore);//+1
});
// dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
NSLog(@"end:%@",semaphore);
6后面的不會(huì)執(zhí)行,信號(hào)量小于0,輸出如下
2018-03-29 17:48:55.679397+0800 TestProject[28407:3448511] 5
2018-03-29 17:48:55.679560+0800 TestProject[28407:3448511] 6
2018-03-29 17:48:57.682849+0800 TestProject[28407:3448635] 2:<NSThread: 0x6040002647c0>{number = 4, name = (null)}
2018-03-29 17:48:57.682849+0800 TestProject[28407:3448618] 1:<NSThread: 0x608000270d80>{number = 3, name = (null)}
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);//創(chuàng)建總數(shù)為0的信號(hào),線程數(shù)1
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"1:%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);//發(fā)送信號(hào),信號(hào)+1
});
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//等待信號(hào),當(dāng)信號(hào)量少于0時(shí)就會(huì)一直等待,否則正常執(zhí)行,并使信號(hào)量-1
NSLog(@"5");
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"2:%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);//發(fā)送信號(hào),信號(hào)+1
});
NSLog(@"6");
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"3:%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);//+1
});
NSLog(@"7");
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"4:%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);//+1
});
// dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
NSLog(@"end:%@",semaphore);
會(huì)等待1執(zhí)行完,輸出結(jié)果如下
2018-03-29 17:53:34.184881+0800 TestProject[28427:3460477] 1:<NSThread: 0x60c000271880>{number = 3, name = (null)}
2018-03-29 17:53:34.185061+0800 TestProject[28427:3460368] 5
2018-03-29 17:53:34.185161+0800 TestProject[28427:3460368] 6
2018-03-29 17:53:36.187280+0800 TestProject[28427:3460477] 2:<NSThread: 0x60c000271880>{number = 3, name = (null)}
2018-03-29 17:53:36.187442+0800 TestProject[28427:3460368] 7
2018-03-29 17:53:36.187581+0800 TestProject[28427:3460368] end:<OS_dispatch_semaphore: 0x60c000091d50>
2018-03-29 17:53:38.190267+0800 TestProject[28427:3460476] 4:<NSThread: 0x60c00026f540>{number = 4, name = (null)}
2018-03-29 17:53:38.190230+0800 TestProject[28427:3460477] 3:<NSThread: 0x60c000271880>{number = 3, name = (null)}
GCD控制并發(fā)數(shù)量
- (void)testSemaphoreTest{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);//所開(kāi)線程數(shù)為n+1
for (int i=0; i<100; ++i) {
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:0.5];
NSLog(@"number:%d thread:%@",i,[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);//發(fā)送信號(hào),信號(hào)+1
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
}
3.NSOperation是蘋(píng)果提供給我們的一套多線程解決方案。比GCD擁有更強(qiáng)的可控性和代碼可讀性,比如我們想cancel一個(gè)任務(wù),控制任務(wù)的優(yōu)先級(jí),用NSOperation就會(huì)很方便。
operation queues顧名思義是用來(lái)存放operation的隊(duì)列,可以通過(guò)設(shè)置最大并發(fā)數(shù)(maxConcurrentOperationCount)來(lái)控制并發(fā),串行。
maxConcurrentOperationCount 默認(rèn)情況下為-1,表示不進(jìn)行限制,可進(jìn)行并發(fā)執(zhí)行。
maxConcurrentOperationCount 為1時(shí),隊(duì)列為串行隊(duì)列。只能串行執(zhí)行
maxConcurrentOperationCount 大于1時(shí),隊(duì)列為并發(fā)隊(duì)列。操作并發(fā)執(zhí)行,當(dāng)然這個(gè)值不應(yīng)超過(guò)系統(tǒng)限制,即使自己設(shè)置一個(gè)很大的值,系統(tǒng)也會(huì)自動(dòng)調(diào)整為 min{自己設(shè)定的值,系統(tǒng)設(shè)定的默認(rèn)最大值}
nsoperation 自帶依賴的建立,很方便
-(void)testOperationDependency {
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
//
NSLog(@"1");
}];
NSBlockOperation *operationTwo = [NSBlockOperation blockOperationWithBlock:^{
//
[NSThread sleepForTimeInterval:5];
NSLog(@"2");
}];
NSBlockOperation *operationThree = [NSBlockOperation blockOperationWithBlock:^{
//
NSLog(@"3");
}];
//1依賴于2的完成
[operation addDependency:operationTwo];
[queue addOperation:operation];
[queue addOperation:operationTwo];
[queue addOperation:operationThree];
}