GCD队列规律
- 同步派发任务只能在当前线程执行
- 异步派发任务可以在其他线程执行
- 串行队列任务只能在一个线程中执行
- 并行队列任务可以在多个线程中执行
系统中提供的队列
- 主队列(串行) 用dispatch_get_main_queue() 获取
- 全局并发队列 用dispatch_get_global(优先级, 0) 获取
四种优先级:
#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
自己创建队列
dispatch_queue_create(const char *_Nullable label,
dispatch_queue_attr_t _Nullable attr)
两种类型:
DISPATCH_QUEUE_SERIAL 串行
DISPATCH_QUEUE_CONCURRENT 并发
队列使用
dispatch_queue_t queue = dispatch_queue_create("com.ly.test",
DISPATCH_QUEUE_CONCURRENT);
/// 同步派发任务
dispatch_sync(queue, ^{
NSLog(@"同步派发任务");
});
/// 异步派发任务
dispatch_async(queue, ^{
NSLog(@"异步派发任务");
});
/// 延迟派发任务
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)),queue, ^{
NSLog(@"延迟10miao派发任务");
});
/// 派发只执行一次的任务
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"派发只执行一次的任务");
});
/// 快速迭代
dispatch_apply(10, queue, ^(size_t index) {
NSLog(@"快速迭代第%zd次", index);
});
栅栏
派发的栅栏任务会等待前面派发的任务完成才开始,
栅栏任务后面的任务必须等待栅栏任务完成才能开始。
/// gcd 栅栏
dispatch_barrier_async(queue, ^{
NSLog(@"gcd 栅栏任务");
});
任务组
dispatch_group_t group = dispatch_group_create();
// 任务归组方式1
dispatch_group_async(group, queue, ^{
NSLog(@"派发任务并归组方式1");
});
// 任务归组方式2
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"派发任务并归组方式2");
dispatch_group_leave(group);
});
/// 阻塞等待(DISPATCH_TIME_FOREVER一直等待; DISPATCH_TIME_NOW 相当于不等待)
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
/// 完成通知
dispatch_group_notify(group, queue, ^{
NSLog(@"任务组完成通知");
});
GCD信号量 dispatch_semaphore
信号量为0时dispatch_semaphore_wait会阻塞线程,
代码运行中如果dispatch_semaphore不能恢复到初始值,会crash。
/// gcd 信号量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(3);
/// 信号量减1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
/// 信号量减1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
/// 信号量减1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
/// 信号量减1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
/// 信号量加1
dispatch_semaphore_signal(semaphore);
/// 信号量加1
dispatch_semaphore_signal(semaphore);
/// 信号量加1
dispatch_semaphore_signal(semaphore);
/// 信号量加1
dispatch_semaphore_signal(semaphore);
与NSOperationQueue比较
NSOperationQueue 是对GCD做了面向对象的封装,任务封装到NSOperation对象中,封装产生的便利性如下:
- NSOperation可取消,有是否取消到状态变量。已开始到任务cancel无效
- NSOperation可设置优先级
- NSOperation之间可设置依赖关系
- NSOperation对象属性支持KVO
NSOperation
@interface NSOperation : NSObject {
@private
id _private;
int32_t _private1;
#if __LP64__
int32_t _private1b;
#endif
}
- (void)start;
- (void)main;
/// 任务取消
@property (readonly, getter=isCancelled) BOOL cancelled;
- (void)cancel;
@property (readonly, getter=isExecuting) BOOL executing;
@property (readonly, getter=isFinished) BOOL finished;
@property (readonly, getter=isConcurrent) BOOL concurrent; // To be deprecated; use and override 'asynchronous' below
@property (readonly, getter=isAsynchronous) BOOL asynchronous API_AVAILABLE(macos(10.8), ios(7.0), watchos(2.0), tvos(9.0));
@property (readonly, getter=isReady) BOOL ready;
/// 依赖关系管理方法
- (void)addDependency:(NSOperation *)op;
- (void)removeDependency:(NSOperation *)op;
@property (readonly, copy) NSArray<NSOperation *> *dependencies;
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
NSOperationQueuePriorityVeryLow = -8L,
NSOperationQueuePriorityLow = -4L,
NSOperationQueuePriorityNormal = 0,
NSOperationQueuePriorityHigh = 4,
NSOperationQueuePriorityVeryHigh = 8
};
@property NSOperationQueuePriority queuePriority;
@property (nullable, copy) void (^completionBlock)(void) API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
- (void)waitUntilFinished API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
@property double threadPriority API_DEPRECATED("Not supported", macos(10.6,10.10), ios(4.0,8.0), watchos(2.0,2.0), tvos(9.0,9.0));
@property NSQualityOfService qualityOfService API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
@property (nullable, copy) NSString *name API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
@end
NSOperationQueue
@interface NSOperationQueue : NSObject {
@private
id _private;
void *_reserved;
}
- (void)addOperation:(NSOperation *)op;
- (void)addOperations:(NSArray<NSOperation *> *)ops waitUntilFinished:(BOOL)wait API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
- (void)addOperationWithBlock:(void (^)(void))block API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
@property (readonly, copy) NSArray<__kindof NSOperation *> *operations;
@property (readonly) NSUInteger operationCount API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
@property NSInteger maxConcurrentOperationCount;
@property (getter=isSuspended) BOOL suspended;
@property (nullable, copy) NSString *name API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
@property NSQualityOfService qualityOfService API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
@property (nullable, assign /* actually retain */) dispatch_queue_t underlyingQueue API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
- (void)cancelAllOperations;
- (void)waitUntilAllOperationsAreFinished;
@property (class, readonly, strong, nullable) NSOperationQueue *currentQueue API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
@property (class, readonly, strong) NSOperationQueue *mainQueue API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
@end
网友评论