写此文章是为了能够加深自己的记忆,并且对技术点有个记录,方便查阅
这篇文章主要写一些iOS多线程的操作
1.NSThread([θred], 英式发音):轻量级的,编程中很少用,需要自己管理线程,加锁等,很复杂,所以平时编程很少用。
比较常用的是获取当前线程和暂停当前线程
- (void)textAction {
NSThread *current = [NSThread currentThread];
NSLog(@"current:%@",current);
[NSThread sleepForTimeInterval:2];
NSLog(@"finish");
}
2.引自百度百科
Grand Central Dispatch(GCD) 是 Apple 开发的一个多核编程的较新的解决方法。它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。它是一个在线程池模式的基础上执行的并发任务。在 Mac OS X 10.6 雪豹中首次推出,也可在 iOS 4 及以上版本使用。
GCD有一套完整的api,使用方便,也应该是在实际开发中用的最多的
GCD中有同步(sync)和异步之分(async),串行和并行队列之分
串行队列(Serial Dispatch Queue):
并行队列(Concurrent Dispatch Queue):
GCD自带的两个队列:
//主线程,串行
dispatch_queue_t mainQueue = dispatch_get_main_queue();
//全局队列,并行
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;
//异步,会开启新线程
dispatch_async(queue, ^{
//
});
//同步,不会开启新线程
dispatch_sync(queue, ^{
//
});
用的比较多的其实是主线程刷新ui
dispatch_async(dispatch_get_main_queue(), ^{
//
});
还有任务组,比如需要把两个请求的结果合并为一个,那么可以是两个异步的请求加入dispatch group,等待两个都返回后,调用group的通知,会告知我们任务组里的任务都完成了
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, ^{
//执行第一个任务
});
dispatch_group_async(group, concurrentQueue, ^{
//执行第二个任务
});
dispatch_group_notify(group, concurrentQueue, ^{
//group 中的任务执行完
});
另外需要注意的是在dispatch_group_async中如果执行的是异步操作的话,则notify会失效,需要用
//确保配对使用
dispatch_group_enter(group);
dispatch_group_leave(group);
gcd还有许多平常我们经常用的的,例如单利的创建
+(instancetype)sharedInstance \
{ \
static CLASS * sharedInstance = nil; \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
sharedInstance = [[CLASS alloc] init]; \
}); \
return sharedInstance; \
}
有时我们需要延迟执行一些操作
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
});
如果需要执行两组任务,第一组必须在第二组之前运行,则可以用栅栏函数解决
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中的信号量semaphore([ˈseməfɔ:(r)])
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);//创建总数为0的信号
dispatch_semaphore_signal(semaphore);//发送信号,信号+1
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//等待信号,当信号量少于0时就会一直等待,否则正常执行,并使信号量-1
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);//创建总数为0的信号
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"1:%@",[NSThread currentThread]);
// dispatch_semaphore_signal(semaphore);//发送信号,信号+1
});
// dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//等待信号,当信号量少于0时就会一直等待,否则正常执行,并使信号量-1
NSLog(@"5");
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"2:%@",[NSThread currentThread]);
// dispatch_semaphore_signal(semaphore);//发送信号,信号+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后面的不会执行,信号量小于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);//创建总数为0的信号,线程数1
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"1:%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);//发送信号,信号+1
});
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//等待信号,当信号量少于0时就会一直等待,否则正常执行,并使信号量-1
NSLog(@"5");
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"2:%@",[NSThread currentThread]);
dispatch_semaphore_signal(semaphore);//发送信号,信号+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);
会等待1执行完,输出结果如下
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控制并发数量
- (void)testSemaphoreTest{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);//所开线程数为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);//发送信号,信号+1
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
}
3.NSOperation是苹果提供给我们的一套多线程解决方案。比GCD拥有更强的可控性和代码可读性,比如我们想cancel一个任务,控制任务的优先级,用NSOperation就会很方便。
operation queues顾名思义是用来存放operation的队列,可以通过设置最大并发数(maxConcurrentOperationCount)来控制并发,串行。
maxConcurrentOperationCount 默认情况下为-1,表示不进行限制,可进行并发执行。
maxConcurrentOperationCount 为1时,队列为串行队列。只能串行执行
maxConcurrentOperationCount 大于1时,队列为并发队列。操作并发执行,当然这个值不应超过系统限制,即使自己设置一个很大的值,系统也会自动调整为 min{自己设定的值,系统设定的默认最大值}
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];
}