在 iOS 中其实目前有 4 套多线程方案,他们分别是:Pthreads、NSThread、GCD、 NSOperation & NSOperationQueue
Pthreads:常用于各种操作系统,基于c语言的框架,一般不用到
NSThread:手动管理生命周期,多用于调试使用
GCD: 分为任务和队列, 优势:底层实现,运行速度快
任务为要执行的代码,以block表示,分为同步任务和异步任务,同步任务会阻塞当前线程
1.队列分为串行和并行,串行队列一步步执行
2.队列组:将很多队列添加到一个队列组中,当组内所有任务执行完毕,有一个方法可以通知我们
串行队列:dispatch_queue_t queue = dispatch_queue_create(“nameID”,DISPATCH_QUEUE_SERIAL);
并行队列:dispatch_queue_t queue = dispatch_queue_create(“nameID”,DISPATCH_QUEUE_CONCURRENT);
串行队列中,系统提供了一个主队列:
dispatch_queue_t queue = dispatch_get_main_queue()
并行队列中,系统提供了一个全局并发队列:
dispatch_queue queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)
同步执行任务:
dispatch_sync(queue,^{
// 任务代码
})
异步执行任务:
dispatch_async(queue,^{
// 任务代码
})
注意:同步执行+主队列 在主线程中调用会死锁
3.栅栏方法
在一个队列中,栅栏任务会在之前任务执行完毕后执行,后续任务会在栅栏任务执行完毕后执行,即排序 任务一、任务二、栅栏任务、任务三、任务四的执行结果是 任务一、任务二异步执行,待执行完两者再执行栅栏任务,执行完毕再异步执行任务三、任务四
dispatch_barrier_async(queue,^{
// 栅栏任务
})
4.延时方法
在指定时间之后将任务添加到队列中
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(2.0*NSEC_PER_SEC)), queue,^{
// 延时任务
})
5.只执行一次代码
保证某段代码在程序运行过程中只被执行一次,保证线程安全
如单例:
-(instance)shareManager
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
//只执行一次的代码
_manager = [[Manager alloc] init];
});
return _manager;
}
6.线程组(队列组) dispatch_group
任务放到队列中,队列放到队列组中
dispatch_group_t group = dispatch_group_creat();
dispatch_group_async(group,queue,^{
// 任务1
})
dispatch_group_async(group,queue,^{
// 任务2
})
监听线程组内任务全部执行完毕 dispatch_group_notify
dispatch_group_notify(group,queue,^{
// 监听线程组内任务执行完毕后执行的任务
});
7.线程阻塞 dispatch_group_enter、dispatch_group_leave
阻塞线程等待前面的线程组内的任务执行完
dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
dispatch_group_enter 标志着一个任务追加到 group,执行一次,相当于 group 中未执行完毕任务数+1
dispatch_group_leave 标志着一个任务离开了 group,执行一次,相当于 group 中未执行完毕任务数-1。
当 group 中未执行完毕任务数为0的时候,才会使dispatch_group_wait解除阻塞,以及执行追加到dispatch_group_notify中的任务。
8.信号量 dispatch_semaphore
• 保持线程同步,将异步执行任务转换为同步执行任务
• 保证线程安全,为线程加锁
dispatch_semaphore_create:创建一个Semaphore并初始化信号的总量
dispatch_semaphore_signal:发送一个信号,让信号总量加1
dispatch_semaphore_wait:可以使总信号量减1,当信号总量为0时就会一直等待(阻塞所在线程),否则就可以正常执行。
NSOperation和NSOperationQueue:NSOperation 和 NSOperationQueue 分别对应 GCD 的 任务 和 队列;将要执行的任务封装到一个 NSOperation 对象中,将此任务添加到一个 NSOperationQueue 对象中
NSOperation 只是一个抽象类,所以不能封装任务。但它有 2 个子类用于封装任务。分别是:NSInvocationOperation 和 NSBlockOperation 。创建一个 Operation 后,需要调用 start 方法来启动任务
除了上面的两种 Operation 以外,我们还可以自定义 Operation。自定义 Operation 需要继承 NSOperation 类,并实现其 main() 方法
任务创建完成后,添加到对应的NSOperationQueue队列中执行
NSOperation 有一个非常实用的功能,那就是添加依赖
[operation2 addDependency:operation1];
单例:
-
(instancetype)sharedTool {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[Tool alloc] init];
});return _instance;
}
网友评论