《iOS高級開發(fā)之多線程編程之三》

主隊列上的同步異步執(zhí)行

  • 主隊列 異步執(zhí)行 在主線程有序執(zhí)行
    dispatch_queue_t queue = dispatch_get_main_queue();
    for (int i = 0; i < 10; i++) {

      dispatch_async(queue, ^{
          NSLog(@"hello---%d %@",i,[NSThread currentThread]);
      });
      
     }
    
主隊列 異步執(zhí)行.png
  • 主隊列 同步執(zhí)行 在主線程上執(zhí)行時會死鎖

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

從運行結果可以明顯看出,程序無法正常執(zhí)行 被死鎖。
接下來看一下鎖死的原因:
當程序運行到下面這段代碼時
<pre> dispatch_sync(queue, ^{
NSLog(@"hello --- %@",[NSThread currentThread]);
}); </pre>
主線程:如果主線程正在執(zhí)行行代碼,就不調度任務
同步執(zhí)行: 如果第一個任務沒有執(zhí)行,就等待第一個任務執(zhí)行完成后,在執(zhí)行下一個任務。導致程序互相等待,造成死鎖。

解決方案

(主隊列 同步執(zhí)行)放入異步執(zhí)行,解決死鎖問題

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

知識拓展

  • 主隊列于串行隊列的區(qū)別
  • 串行隊列: 必須的一個任務調度完成,再去執(zhí)行另一個任務
  • 主隊列: 以先進先出的調度任務,如果主線程上有任務在執(zhí)行,主隊列不會調用任務

走進NSOperation

  • NSOperation是一個抽象的類
  • 不能直接使用(方法沒有實現(xiàn))
  • 結束子類都具有共同的屬性和方法
  • NSOperation的子類
  • NSInvocationOperation
  • NSBlockOperation
  • 自定義operation
  • NSOperationQueue隊列
  • NSInvocationOperation

  • 新建一個NSInvocationOperation對象

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

默認情況下,調用start方法并不會開一條新線程執(zhí)行操作,而是在當前線程同步執(zhí)行操作,只有將一個NSOperation放到NSOperationQueue中,才會異步執(zhí)行操作

接下來我們來測試一下
 - (void)viewDidLoad {
[super viewDidLoad];
//NSInvocationOperation操作
    //創(chuàng)建操作
  NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(diown) object:nil];
//創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//異步執(zhí)行
[queue addOperation:operation];
//同步執(zhí)行

 }
 -(void) diown{
NSLog(@"download --- %@",[NSThread currentThread]);
}
Snip20170409_7.png

可以看出,在子線程中執(zhí)行的。如果沒有將NSOperation放到NSOperationQueue中,將會同步執(zhí)行,這里不做演示了

  • NSBlockOperation

  • 新建一個 NSBlockOperation對象

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

*創(chuàng)建addExecutionBlock:方法添加更多操作
- (void)addExecutionBlock:(void (^)(void))block;

注意

只要NSBlockOperation封裝的操作 >1 就會執(zhí)行,異步操作

接下來我們來測試一下
  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方法來調用任務,但是默認是同步執(zhí)行。如果將NSOperation添加到NSOperationQueue的隊列中,系統(tǒng)會自動,異步執(zhí)行

  • 添加操作到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]);
 }
  • 第二種(創(chuàng)建全程隊列)--相比第一種,這一種更為簡便
 @interface ViewController ()
 //創(chuàng)建一個全程隊列
 @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]);
    }];
}];
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容