美文网首页
GCD&NSOperationQueue

GCD&NSOperationQueue

作者: GTMYang | 来源:发表于2019-05-16 13:45 被阅读0次

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

相关文章

  • GCD&NSOperationQueue

    GCD队列规律 同步派发任务只能在当前线程执行 异步派发任务可以在其他线程执行 串行队列任务只能在一个线程中执行 ...

网友评论

      本文标题:GCD&NSOperationQueue

      本文链接:https://www.haomeiwen.com/subject/gqkbaqtx.html