iOS 关于GCD和NSOperation的部分记录

2018-08-20  本文已影响26人  c608
1:GCD线程的同步异步和串行并行

参考链接

链接截图
这个图倒是很好的解释了其中关系,链接中每种情况的例子讲解的都很详细

实际开发中,模拟一个消息接受机制:一次性推过来多条消息,并写入到数据库中,这个时候可以用到串行队列+异步线程,确保消息逐条写入到数据库中

//模拟消息
    [[self.operationBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
//        [self addOperationQueue];
        //模拟消息瞬间推过来10条
        for (int i = 0; i < 10; i++) {
            [self dispatchAsync:i];
        }
    }];
//消息处理机制
- (void)dispatchAsync:(NSInteger )index{
    NSLog(@"mainThread---%@", [NSThread currentThread]); // 打印主线程
//创建一个异步线程  dispatch_async
    dispatch_async(self.queue, ^{
        [NSThread sleepForTimeInterval:2]; // 模拟写入数据库操作
        NSLog(@"1 == %@  %ld",[NSThread currentThread],index);
    });
//    dispatch_async(self.queue, ^{
//        [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
//        NSLog(@"2 == %@",[NSThread currentThread]);
//    });
}
//懒加载属性队列
- (dispatch_queue_t)queue {
    if (!_queue) {
//创建一个同步队列 DISPATCH_QUEUE_SERIAL  (异步队列的话关键字是DISPATCH_QUEUE_CONCURRENT)
        _queue = dispatch_queue_create("signQueue", DISPATCH_QUEUE_SERIAL);
    }
    return _queue;
}
打印结果 消息打印结果

这样确保了消息的写入操作是按照顺序执行
链接文章里讲了多种线程的使用场景,同学们可以自行根据项目需求来用

2:NSOperation的依赖

使用场景:A操作的执行需要B和C操作执行结束才执行
个人感觉这个类似于GCD中栅栏(dispatch_barrier_async)的作用

- (void)addDependency:(NSOperation *)op; 添加依赖,使当前操作依赖于操作 op 的完成。
- (void)addOperationQueue{
    NSLog(@"mainThread---%@", [NSThread currentThread]); // 打印主线程
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];//创建队列
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
            NSLog(@"1---%@", [NSThread currentThread]); // 打印当前线程
        }
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
            NSLog(@"2---%@", [NSThread currentThread]); // 打印当前线程
        }
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 2; i++) {
            [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
            NSLog(@"3---%@", [NSThread currentThread]); // 打印当前线程
        }
    }];
    //添加依赖
    [op1 addDependency:op2];
    [op1 addDependency:op3];
    //添加到队列中
    [queue addOperation:op1];
    [queue addOperation:op2];
    [queue addOperation:op3];
    
}
任务执行顺序结果

确保了任务2和任务3执行完毕,再执行队列中的任务1

3:GCD 信号量:dispatch_semaphore

通过信号量Dispatch Semaphore 确保线程安全和线程同步(为线程加锁)
需求:异步执行耗时任务,并使用异步执行的结果进行一些额外的操作也就是将异步执行任务转换为同步执行任务

Dispatch Semaphore 提供了三个函数。
dispatch_semaphore_create:创建一个Semaphore并初始化信号的总量
dispatch_semaphore_signal:发送一个信号,让信号总量加1
dispatch_semaphore_wait:可以使总信号量减1,当信号总量为0时就会一直等待(阻塞所在线程),否则就可以正常执行。

- (void)semaphore{
    __block NSInteger num = 0;
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);//创建信号量并给初始值为0
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [NSThread sleepForTimeInterval:2];              // 模拟耗时操作
        NSLog(@"1---%@",[NSThread currentThread]);      // 打印当前线程
        num = 100;
        dispatch_semaphore_signal(semaphore);//发送信号
    });
      NSLog(@"查看信号量之前的num的值:%ld",num);
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    NSLog(@"查看此时num的值:%ld",num);
}
信号量前后num的值
上一篇下一篇

猜你喜欢

热点阅读