美文网首页
iOS学习-多线程3

iOS学习-多线程3

作者: 快乐的tomato | 来源:发表于2021-09-14 21:37 被阅读0次

9、延迟dispatch_after

dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC); 
dispatch_after(timer, dispatch_get_main_queue(), ^{
[self doSomething]
});

10、一次性执行dispatch_once

static dispatch_once_t predicate;
 dispatch_once(&predicate, ^{ 
       // some one-time task
 });

在当前线程上执行

  • 原理:
    判断静态全局变量的值,默认是0,如果执行完成后,设置为-1
    once内部会判断变量的值,如果是0,才执行
  • dispatch_once 本身就是线程安全的。
单例
+(instancetype)sharedTools{

    static NetworkTools *tools;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
    });
    return tools;
}

11、调度组dispatch_group

场景:
下载3首歌曲,全部下载完成之后,回到主线程程通知用户

//    1、创建调度组:
    dispatch_group_t group = dispatch_group_create();

//    2、创建并发任务:
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_group_async(group, queue, ^{
        NSLog(@"正在下载歌曲1");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"正在下载歌曲2");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"正在下载歌曲3");
    });
    
//  3、接收通知:
    // 当group中所有操作执行完成后发出通知
    dispatch_group_notify(group, queue, ^{
        
        NSLog(@"全部下载完成%@", [NSThread currentThread]);
    });

2021-09-13 20:12:19.255006+0800 OCStudy[44177:948448] 正在下载歌曲1
2021-09-13 20:12:19.255115+0800 OCStudy[44177:950228] 正在下载歌曲3
2021-09-13 20:12:19.255010+0800 OCStudy[44177:950227] 正在下载歌曲2
2021-09-13 20:12:19.255718+0800 OCStudy[44177:950227] 全部下载完成<NSThread: 0x600002d58640>{number = 7, name = (null)}

  • 原理
//GCD调度组原理方法
 
 //创建调度组和队列
    dispatch_group_t group = dispatch_group_create();
     dispatch_queue_t queue = dispatch_queue_create("YuanLi", DISPATCH_QUEUE_CONCURRENT);
 
      //任务1
      dispatch_group_enter(group);
     dispatch_async(queue, ^{
       NSLog(@"任务1");
       dispatch_group_leave(group);
    });
    
   //任务2
     dispatch_group_enter(group);
     dispatch_async(queue, ^{
         [NSThread sleepForTimeInterval:2];
         NSLog(@"任务2");
        dispatch_group_leave(group);
     });
     
     //任务3
    dispatch_group_enter(group);
     dispatch_async(queue, ^{
         NSLog(@"任务3");
         dispatch_group_leave(group);
     });
     
    //任务全部执行完毕
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
      
       NSLog(@"任务执行完毕, 刷新UI");
   });
   
   //等待上面代码执行完毕后在执行下面的代码, 参数2:等待超时时间
   //dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
     
    NSLog(@"Hello");
 }

三、NSOperation

1、是什么?

NSOperation是对GCD的封装,面向对象,比GCD更易于使用。

2、优点

可添加完成的代码块,添加操作之间的依赖,方便控制之下顺序,可以设定优先级,可使用kvo观察操作执行状态。

NSOperation是一个抽象类,不能直接使用,有2个抽象类NSInvocationOperation,NSBlockOperation

3、NSInvocationOperation

NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    queue.maxConcurrentOperationCount = 2;

    NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^{
        
            for (int i = 0; i<5; i++) {
                NSLog(@"第%d次 执行任务 %@",i+1,[NSThread currentThread]);
            }
        }];
        
    [bo addExecutionBlock:^{

        for (int i = 0; i<5; i++) {
            NSLog(@"第%d次 执行额外任务 %@",i+1,[NSThread currentThread]);
        }
    }];

    [queue addOperation:bo];

    [queue addOperationWithBlock:^{
            
    }];
    
//    从输出结果可以看出来一些东西
//    1.任务并不是先执行任务后执行额外任务,而是相互穿插。
//    2.虽然跟理想中的结果不太一样,但是不论任务跟额外任务,却按照12345的顺序,老老实实的执行。
    
//    这里 maxConcurrentOperationCount 控制的不是并发线程的数量,而是一个队列中同时能并发执行任务的最大数。而且一个任务也并非只能在一个线程中运行。

4、NSBlockOperation

 //在操作没有添加到队列中,操作直接start,任务是在主线程上执行,没有开启线程
    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"这是NSBlockOperation执行的任务 %@",[NSThread currentThread]);
        }];
//    [blockOperation start];

    //给block多加几个任务
//   给操作添加额外任务,并不会让这些任务按顺序执行。
//    但是初始化的任务仍然在主线程执行,另外两个任务分别创建了线程。 所以NSBlockOperation是否创建线程,取决于当前需要执行的任务数。
    [blockOperation addExecutionBlock:^{
            
        NSLog(@"Block任务1 %@",[NSThread currentThread]);
    }];
    [blockOperation addExecutionBlock:^{
            
        NSLog(@"Block任务2 %@",[NSThread currentThread]);
    }];
    [blockOperation start];

//    总结一下
//    1.NSBlockOperation是否创建线程,取决于当前需要执行的任务数。
//    2.blockOperationWithBlock里面的任务,不一定在主线程执行。
    

5、优先级

操作优先级:没有什么意义 ,还是会交叉执行,达不到理想效果

6、操作依赖

//设置操作依赖来保证执行顺序


   
   NSOperationQueue *queue = [[NSOperationQueue alloc] init];
   NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
       
       for (int i = 0; i<5; i++) {
           NSLog(@"op1 %d",i);
       }
   }];
   
   NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
       
       for (int i = 0; i<5; i++) {
           NSLog(@"op2 %d",i);
       }
   }];
   
   NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
       
       for (int i = 0; i<5; i++) {
           NSLog(@"op3 %d",i);
       }
   }];
   
   [op2 addDependency:op1];
   [op3 addDependency:op2];

   [queue addOperations:@[op1,op2,op3] waitUntilFinished:NO];

7、控制最大并发数(实现同步)

NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    queue.maxConcurrentOperationCount = 1;

    NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^{
        
            for (int i = 0; i<5; i++) {
                NSLog(@"第%d次 执行任务 %@",i+1,[NSThread currentThread]);
            }
        }];
        
    [bo addExecutionBlock:^{

        for (int i = 0; i<5; i++) {
            NSLog(@"第%d次 执行额外任务 %@",i+1,[NSThread currentThread]);
        }
    }];

    [queue addOperation:bo];

    [queue addOperationWithBlock:^{
            
    }];
    
//    从输出结果可以看出来一些东西
//    1.任务并不是先执行任务后执行额外任务,而是相互穿插。
//    2.虽然跟理想中的结果不太一样,但是不论任务跟额外任务,却按照12345的顺序,老老实实的执行。
    
//    这里 maxConcurrentOperationCount 控制的不是并发线程的数量,而是一个队列中同时能并发执行任务的最大数。而且一个任务也并非只能在一个线程中运行。

相关文章

网友评论

      本文标题:iOS学习-多线程3

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