iOS NSThread、NSOperation与GCD

对着背影说爱祢 提交于 2020-03-02 11:43:34

一、NSThread线程

优点:

NSThread 比其他两个轻量级、使用方便、简洁。

缺点:

①需要自己管理线程的生命周期。

②线程同步,线程同步对数据的加锁会有一定的系统开销

 

NSThread线程的使用:

启动一个线程

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(myThreadTask) object:nil];
thread.name=@"sum";
[thread start]

停止线程

[thread  cancel];
thread = nil;

注意:停止线程的并不是直接杀死线程,而是设置了个标记

-(void) myThreadTask{

    @autoreleasepool {
        NSLog(@"Thread Entry Point");
        while ([[NSThread currentThread] isCancelled] == NO){
            [NSThread sleepForTimeInterval:10];
            NSLog(@"Thread Loop");
        }
        NSLog(@"Thread Finished");
    }

}

 

还有一类用法如下:

[NSThread detachNewThreadSelector:@selector(bigDemo) toTarget:self withObject:nil];

 

二、NSOperation

优点:

① 底层实现自GCD,相对高效

② 内部线程池可以更好的管理子线程

③可以设置线程执行的优先级和依赖关系

 

NSOperation的用法:

1.无依赖关系

NSOperationQueue *queue = [[NSOperationQueue alloc] init];  
  
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^(){  
    NSLog(@"执行第1次操作,线程:%@", [NSThread currentThread]);  
}];  
  
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^(){  
    NSLog(@"执行第2次操作,线程:%@", [NSThread currentThread]);  
}];  
  
[queue addOperation:operation1];  
[queue addOperation:operation2]; 

2.设置依赖关系

NSOperationQueue *queue = [[NSOperationQueue alloc] init];  
  
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^(){  
    NSLog(@"执行第1次操作,线程:%@", [NSThread currentThread]);  
}];  
  
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^(){  
    NSLog(@"执行第2次操作,线程:%@", [NSThread currentThread]);  
}];  
// operation1依赖于operation2  
[operation1 addDependency:operation2];   //那么2先执行,接下来1才能执行
  
[queue addOperation:operation1];  
[queue addOperation:operation2]; 

 

3.设置线程最大并发数量,一般并发量取决于cpu核心数

queue.maxConcurrentOperationCount = 3;  

 

三、GCD多线程

GCD的底层依然是用线程实现,让程序平行排队的特定任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。

优点:

①高效、可以选择各种队列

②可扩展性高

缺点:

①无法实现多线程同步,线程同步需要借助信号量来实现

②无法直接取消指定的任务

 

GCD使用场景一:

单例

+ (instancetype)defaultViewController {

      static ViewController *vc = nil; 
      static dispatch_once_t onceToken;

      dispatch_once(&onceToken, ^{
           vc = [[ViewController alloc] init];      

      });

         return vc;

}

图片异步加载的实现

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{

   NSURL*url = [NSURLURLWithString:@"http://img5.netease.com/img/20151030124521.jpg"];

   NSData*data = [NSDatadataWithContentsOfURL:url];
   UIImage*image = [UIImageimageWithData:data];

  // GCD返回主线程UI赋值
  dispatch_sync(dispatch_get_main_queue(), ^{

    self.imageView.image= image;

  });

});

并发

dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //请求1
        NSLog(@"Request_1");
    });
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //请求2
        NSLog(@"Request_2");
    });
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //请求3
        NSLog(@"Request_3");
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        //界面刷新
        NSLog(@"任务均完成,刷新界面");
    });

通过barrier控制并发量

barrier:表示栅栏,当在并发队列里面使用栅栏时候,栅栏之前的并发任务开始并发执行,执行完毕后,执行栅栏内的任务,等栅栏任务执行完毕后,再并发执行栅栏后的任务。

dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^(){
    NSLog(@"dispatch-1");
});
dispatch_async(concurrentQueue, ^(){
    NSLog(@"dispatch-2");
});
dispatch_barrier_async(concurrentQueue, ^(){
    NSLog(@"dispatch-barrier"); 
});
dispatch_async(concurrentQueue, ^(){
    NSLog(@"dispatch-3");
});
dispatch_async(concurrentQueue, ^(){
    NSLog(@"dispatch-4");
});

 

四、向主线程发送消息

普通对象

MyThread *newThread = [[MyThread alloc] init];
NSObject * plainObject  = newThread;
[plainObject performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:YES]

NSOperation

 NSBlockOperation *b=[NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"%@",[NSThread currentThread]);
  }];

[[NSOperationQueue mainQueue]addOperation:b];

dispatch

  dispatch_sync(dispatch_get_main_queue(), ^{

    self.imageView.image= image;

  });

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!