iOS NSThread、NSOperation與GCD

1、NSThread線程

優勢:多線程

NSThread 比其餘兩個輕量級、使用方便、簡潔。併發

缺點:異步

①須要本身管理線程的生命週期。async

②線程同步,線程同步對數據的加鎖會有必定的系統開銷oop

 

NSThread線程的使用:url

啓動一個線程spa

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

中止線程.net

[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");
    }

}

 

還有一類用法以下:code

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

 

2、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;

 

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");
});

 

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;

  });
相關文章
相關標籤/搜索