美文网首页多线程
《iOS高级开发之多线程编程之三》

《iOS高级开发之多线程编程之三》

作者: 皖北威威猫 | 来源:发表于2017-04-10 12:44 被阅读30次

    主队列上的同步异步执行

    • 主队列 异步执行 在主线程有序执行
      dispatch_queue_t queue = dispatch_get_main_queue();
      for (int i = 0; i < 10; i++) {

        dispatch_async(queue, ^{
            NSLog(@"hello---%d %@",i,[NSThread currentThread]);
        });
        
       }
      
    主队列 异步执行.png
    • 主队列 同步执行 在主线程上执行时会死锁

      dispatch_queue_t queue = dispatch_get_main_queue();
        //测试执行
        NSLog(@"begin");
      
        for (int i = 0; i < 10; i++) {
       dispatch_sync(queue, ^{
           NSLog(@"hello --- %@",[NSThread currentThread]);
       });
        }
        //测试执行
        NSLog(@"end");
      
    主队列 同步执行.png
    分析

    从运行结果可以明显看出,程序无法正常执行 被死锁。
    接下来看一下锁死的原因:
    当程序运行到下面这段代码时
    <pre> dispatch_sync(queue, ^{
    NSLog(@"hello --- %@",[NSThread currentThread]);
    }); </pre>
    主线程:如果主线程正在执行行代码,就不调度任务
    同步执行: 如果第一个任务没有执行,就等待第一个任务执行完成后,在执行下一个任务。导致程序互相等待,造成死锁。

    解决方案

    (主队列 同步执行)放入异步执行,解决死锁问题

     dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_queue_t queue1 = dispatch_get_global_queue(0, 0);
    //测试执行
    NSLog(@"begin");
    dispatch_async(queue1, ^{
        for (int i = 0; i <10; i++) {
            dispatch_sync(queue, ^{
                NSLog(@"hello---%d %@",i,[NSThread currentThread]);
            });
        }
    });
    //测试执行
    NSLog(@"end");
    
    Snip20170409_6.png

    知识拓展

    • 主队列于串行队列的区别
    • 串行队列: 必须的一个任务调度完成,再去执行另一个任务
    • 主队列: 以先进先出的调度任务,如果主线程上有任务在执行,主队列不会调用任务

    走进NSOperation

    • NSOperation是一个抽象的类
    • 不能直接使用(方法没有实现)
    • 结束子类都具有共同的属性和方法
    • NSOperation的子类
    • NSInvocationOperation
    • NSBlockOperation
    • 自定义operation
    • NSOperationQueue队列
    • NSInvocationOperation

    • 新建一个NSInvocationOperation对象

        - (id)initWithTarget:(id)target selector:(SEL)sel object:(nullable id)arg;
    
    • 调用start方法开始执行操作
      - (void) start;
      一旦执行操作,就回到用start 的sel方法
    注意

    默认情况下,调用start方法并不会开一条新线程执行操作,而是在当前线程同步执行操作,只有将一个NSOperation放到NSOperationQueue中,才会异步执行操作

    接下来我们来测试一下
     - (void)viewDidLoad {
    [super viewDidLoad];
    //NSInvocationOperation操作
        //创建操作
      NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(diown) object:nil];
    //创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    //异步执行
    [queue addOperation:operation];
    //同步执行
    
     }
     -(void) diown{
    NSLog(@"download --- %@",[NSThread currentThread]);
    }
    
    Snip20170409_7.png

    可以看出,在子线程中执行的。如果没有将NSOperation放到NSOperationQueue中,将会同步执行,这里不做演示了

    • NSBlockOperation

    • 新建一个 NSBlockOperation对象

        + (instancetype)blockOperationWithBlock:(void (^)(void))block;
    

    *创建addExecutionBlock:方法添加更多操作
    - (void)addExecutionBlock:(void (^)(void))block;

    注意

    只要NSBlockOperation封装的操作 >1 就会执行,异步操作

    接下来我们来测试一下
      NSBlockOperation *operation = [[NSBlockOperation alloc]init];
    [operation addExecutionBlock:^{
        NSLog(@"----下载图片--1---%@",[NSThread currentThread]);
        
    }];
    [operation addExecutionBlock:^{
         NSLog(@"----下载图片--2---%@",[NSThread currentThread]);
    }];
    [operation start];
    
    Snip20170409_8.png
    • NSOperationQueue

    • NSOperationQueue的作用

    NSOperation可以调用start方法来调用任务,但是默认是同步执行。如果将NSOperation添加到NSOperationQueue的队列中,系统会自动,异步执行

    • 添加操作到NSOperationQueue中
      - (void)addOperation:(NSOperation *)op;
      - (void)addOperationWithBlock:(void (^)(void))block ;
    

    下面将演示这两种不同的添加方式

    • 第一种
       NSOperationQueue *queue = [[NSOperationQueue alloc]init];
       NSInvocationOperation *op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(deom) object:nil];
      [op start];
      [queue addOperation:op];
     - (void) demo{
        NSLog(@"%@",[NSThread currentThread]);
     }
    
    • 第二种(创建全程队列)--相比第一种,这一种更为简便
     @interface ViewController ()
     //创建一个全程队列
     @property (nonatomic, strong) NSOperationQueue *queue;
    @end
    //懒加载
    - (NSOperationQueue *)queue{
    if (_queue == nil) {
        _queue = [[NSOperationQueue alloc]init];
    }
    return _queue;
    }
    [self.queue addOperationWithBlock:^{
       
        NSLog(@"qqq %@",[NSThread currentThread]);
    
        NSLog(@"下载图片");
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            NSLog(@"回到主线程");
            NSLog(@"%@",[NSThread currentThread]);
        }];
    }];

    相关文章

      网友评论

        本文标题:《iOS高级开发之多线程编程之三》

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