iOS 中实现多线程的几种方式:
dispatch
NSOperation
performSelector
NSThread
pthread
一、dispatch,对pthread的封装
1. dispatch_sync 和 dispatch_aync
dispatch_sync 程序会等待 dispatch_sync 同步执行完成之后才能继续往下走。
dispatch_aync 程序讲任务添加到队列后继续往下执行,不必等待任务执行完成;一定不会开启新线程;以下代码会发生死锁:
// 例1:同步往当前串行队列添加任务,会产生死锁
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_sync(dispatch_get_main_queue(), ^{
});
}
2. 创建和获取队列。
获取主队列:
dispatch_get_main_queue()
获取后台队列:
// 第一个参数队列优先级,不同优先级获取到的queue不同 // #define DISPATCH_QUEUE_PRIORITY_HIGH 2 // #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // #define DISPATCH_QUEUE_PRIORITY_LOW (-2) // #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 第二个参数不为0时,获取不到queue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
创建串行队列:
dispatch_queue_t serialQueue = dispatch_queue_create("serial", NULL);
创建并发队列:
dispatch_queue_t serialQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
3. dispatch_group 等待被添加到group中的所有任务执行完毕,配合 dispatch_group_notify 或者 dispatch_group_wait。
dispatch_group_t group = dispatch_group_create(); dispatch_queue_t queue = dispatch_queue_create("queue 2", DISPATCH_QUEUE_CONCURRENT); for (int i = 0; i < 10; i++) { dispatch_group_async(group, queue, ^{ NSLog(@"任务 %ld", (long)i); }); } dispatch_group_notify(group, queue, ^{ NSLog(@"任务执行完毕"); });
4. dispatch_after,延迟执行,一段时间后将指定的block到追加某队列中
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC); dispatch_after(time, dispatch_get_main_queue(),^{ NSLog(@"3秒后"); });
5、dispatch_barrier_async,dispatch_barrier_async函数会等待追加到 queue 上的任务全部执行结束之后,再将指定的任务追加到该并发队列中,并且该处理执行完毕之后queue才会恢复为一般动作。
以下代码的执行顺序:
// 第一部分,并发执行
// 第二部分,barrier block 2 执行
// 第二部分,barrier block 2 执行
// 第三部分 并发执行
dispatch_queue_t queue = dispatch_queue_create("queue 2", DISPATCH_QUEUE_CONCURRENT); for (int i = 0; i < 10; i++) { dispatch_async(queue, ^{ NSLog(@"任务 %ld", (long)i); // 第一部分,并发执行 }); } // 第二部分,barrier block 1执行 dispatch_barrier_sync(queue, ^{ for (int i = 0; i < 10; i++) { NSLog(@"dispatch_barrier_sync %ld", (long)i); // 当前线程执行 } }); // 第二部分,barrier block 2 执行 dispatch_barrier_async(queue, ^{ for (int i = 0; i < 10; i++) { NSLog(@"dispatch_barrier_async %ld", (long)i); // 后台线程执行 } }); // 第三部分 并发执行 for (int i = 10; i < 20; i++) { dispatch_async(queue, ^{ NSLog(@"任务 %ld", (long)i); }); }
6、dispatch_semaphore,信号量,通常用与线程同步,当信号量的值小于1时候,线程进入休眠状态等待,直到dispatch_semaphore信号量大于0
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); NSLog(@"1"); dispatch_async(dispatch_get_global_queue(0, 0), ^{ dispatch_semaphore_signal(semaphore); NSLog(@"2"); }); dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); NSLog(@"3");
输出顺序 1 2 3
7、dispatch_once 执行一次,通常用于实现单例
+ (instancetype)sharedInstance { static id sharedInstance; static dispatch_once_t once; dispatch_once(&once, ^{ sharedInstance = [[[self class] alloc] init]; }); return sharedInstance; }
二、NSOperation、NSOperationQueue,对NSthread的封装,更加面向对象,使用起来更加方便,可以设置任务优先级和依赖关系,控制最大执行数量 等。NSOperationQueue 在任务被添加后自动异步执行。
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue setMaxConcurrentOperationCount:5]; for (int i = 0; i < 10; i++) { [queue addOperation:[NSBlockOperation blockOperationWithBlock:^{ NSLog(@"operation %ld, %@", (long)i, [NSThread currentThread]); }]]; } NSOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"op1 %@", [NSThread currentThread]); }]; NSOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"op2 %@",[NSThread currentThread]); }]; NSOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"op3 %@", [NSThread currentThread]); }]; [op1 addDependency:op2]; [op2 addDependency:op3]; [queue addOperation:op2]; [queue addOperation:op3]; [queue addOperation:op1];
三、performSelectorInBackground、performSelectorOnMainThread
NSObject封装的一系列多线程方法。
[self performSelectorInBackground:@selector(operation) withObject:nil]; [self performSelectorOnMainThread:@selector(operation) withObject:nil waitUntilDone:NO]; [self performSelector:@selector(operation) onThread:[[NSThread alloc] init] withObject:nil waitUntilDone:NO];
四、NSThread
[[NSThread alloc] initWithBlock:^{ NSLog(@"任务1"); }]; [[NSThread alloc] initWithTarget:self selector:@selector(operation) object:nil];
五、pthread(POSIX threads,简称Pthreads,是线程的POSIX标准,类Unix操作系统中均使用的操作系统线程)
void *pthreadExecute(void *data) { for (int i = 0; i < 100; i++) { NSLog(@"pthread 执行 %ld, %@", (long)i, [NSThread currentThread]); sleep(1); } return NULL; } - (void)pthread { pthread_t pth; pthread_create(&pth, NULL, pthreadExecute, NULL); sleep(10); pthread_cancel(pth); NSLog(@"pthread cancel %@", [NSThread currentThread]); } 2020-06-08 16:16:36.523342+0800 多线程[6001:678321] pthread 执行 0, <NSThread: 0x600002ccc340>{number = 6, name = (null)} 2020-06-08 16:16:37.524526+0800 多线程[6001:678321] pthread 执行 1, <NSThread: 0x600002ccc340>{number = 6, name = (null)} 2020-06-08 16:16:38.525049+0800 多线程[6001:678321] pthread 执行 2, <NSThread: 0x600002ccc340>{number = 6, name = (null)} 2020-06-08 16:16:39.526688+0800 多线程[6001:678321] pthread 执行 3, <NSThread: 0x600002ccc340>{number = 6, name = (null)} 2020-06-08 16:16:40.527975+0800 多线程[6001:678321] pthread 执行 4, <NSThread: 0x600002ccc340>{number = 6, name = (null)} 2020-06-08 16:16:41.533475+0800 多线程[6001:678321] pthread 执行 5, <NSThread: 0x600002ccc340>{number = 6, name = (null)} 2020-06-08 16:16:42.539034+0800 多线程[6001:678321] pthread 执行 6, <NSThread: 0x600002ccc340>{number = 6, name = (null)} 2020-06-08 16:16:43.539568+0800 多线程[6001:678321] pthread 执行 7, <NSThread: 0x600002ccc340>{number = 6, name = (null)} 2020-06-08 16:16:44.542963+0800 多线程[6001:678321] pthread 执行 8, <NSThread: 0x600002ccc340>{number = 6, name = (null)} 2020-06-08 16:16:45.544117+0800 多线程[6001:678321] pthread 执行 9, <NSThread: 0x600002ccc340>{number = 6, name = (null)} 2020-06-08 16:16:46.524624+0800 多线程[6001:678116] pthread cancel <NSThread: 0x600002c8cd40>{number = 1, name = main}