iOS線程問(wèn)題匯總

   #1:如何使用dispatch source實(shí)現(xiàn)一個(gè)精準(zhǔn)的定時(shí)器。
   dispatch source是一個(gè)監(jiān)視某些類(lèi)型事件的對(duì)象。當(dāng)這些事件發(fā)生時(shí),它自動(dòng)將一個(gè)block放入一個(gè)dispatch queue的執(zhí)行例程中。
   它支持所有kqueue所支持的事件以及mach端口、內(nèi)建計(jì)時(shí)器支持(這樣我們就不用使用超時(shí)參數(shù)來(lái)創(chuàng)建自己的計(jì)時(shí)器)和用戶事件。
   首先定義倒計(jì)時(shí)接口需要的參數(shù):
   TimeCountDown.h
     @class TimeCountDown;
     @protocol TimeCountDownDelegate <NSObject>
     @optional
     - (void)timeCountDownPerSecond;
     @end

     @interface TimeCountDown : NSObject

     //Delegate
     @property(assign,nonatomic) id<TimeCountDownDelegate> delegate;

     //倒計(jì)時(shí)時(shí)間
     @property(assign,nonatomic) NSInteger timeInterval;

     //開(kāi)始時(shí)間
    -(void)startTimer:(NSInteger)timeInterval;

     //停止時(shí)間
    -(void)stopTimer;
    @end
    TimeCountDown.m中
      @interface TimeCountDown(){

              dispatch_source_t _processingQueueSource;
      }

      @property (atomic, assign, getter=isRunning) BOOL running;

      @end

      @implementation TimeCountDown

      -(void)stopTimer{
            [self pause];
      }

      -(void)startTimer:(NSInteger)timeInterval{
              _timeInterval=timeInterval;
               WEAKSELF
              if (_processingQueueSource) {
                   _processingQueueSource  = nil;
               }

        NSInteger totalTime = self.timeInterval;

_processingQueueSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0,
                                                dispatch_get_main_queue());
dispatch_source_set_event_handler(_processingQueueSource, ^{

    if (weakSelf.timeInterval<=0) {
        _processingQueueSource = nil;
    }else{
        weakSelf.timeInterval--;
    }
    if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(timeCountDownPerSecond)]) {
        [weakSelf.delegate timeCountDownPerSecond];
    }
    
});

     [self resume];
     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     dispatch_async(queue, ^{
    
         for (NSUInteger index = 0; index <totalTime; index++) {
         dispatch_source_merge_data(_processingQueueSource, 1);
         unsleep(1000000);//1秒
     }
  });
}

 //獲取分派源分派處理程序之前恢復(fù)
  - (void)resume {
        if (self.running)   return;
        self.running = YES;
        dispatch_resume(_processingQueueSource);
   }

    //暫停
   - (void)pause {
       if (!self.running)   return;
       self.running = NO;
       dispatch_suspend(_processingQueueSource);
   }
  @end
  
  #2:線程死鎖問(wèn)題:
          - (void)viewDidLoad {
                   [super viewDidLoad];
                    dispatch_sync(dispatch_get_main_queue(), ^{
                         NSLog(@"同步線程處理block");
                     });
          }
    #死鎖原因
     #1:dispatch_sync在等待block語(yǔ)句執(zhí)行完成,而block語(yǔ)句需要在主線程里執(zhí)行,所以dispatch_sync如果在主線程調(diào)用就會(huì)造成死鎖
     #2:dispatch_sync是同步的,本身就會(huì)阻塞當(dāng)前線程,也即主線程。而又往主線程里塞進(jìn)去一個(gè)block,所以就會(huì)發(fā)生死鎖。
     #dispatch_async(dispatch_get_global_queue(), ^{
     #async 在主線程中 創(chuàng)建了一個(gè)異步線程 加入 全局并發(fā)隊(duì)列,async 不會(huì)等待     block 執(zhí)行完成,立即返回
     });
     }
     分析這段代碼:view DidLoad 在主線程中,也即dispatch_get_main_queue()中,執(zhí)行到sync時(shí)向dispatch_get_main_queue()插入同步thread,sync會(huì)等到后面的block執(zhí)行完成才返回。sync又在主隊(duì)列里面,是個(gè)串行隊(duì)列,sync是后面才加入的,前面一個(gè)是主線程,所以sync想執(zhí)行block必須等待前一個(gè)主線程執(zhí)行完成,而主線程卻在等待sync返回,去執(zhí)行后續(xù)工作,從而造成死鎖。
 #2:dispatch_sync 和 dispatch_async 區(qū)別:
      dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
           NSLog(@"1");
      dispatch_sync(concurrentQueue, ^(){
           NSLog(@"2");
          [NSThread sleepForTimeInterval:5];
           NSLog(@"3");
       });
           NSLog(@"4");

               NSLog(@"11");
          dispatch_async(concurrentQueue, ^(){
               NSLog(@"21");
              [NSThread sleepForTimeInterval:5];
              NSLog(@"31");
       });
              NSLog(@"41");
 #dispatch_async(queue,block) async 異步隊(duì)列,dispatch_async 函數(shù)會(huì)立即返回, block會(huì)在后臺(tái)異步執(zhí)行。
 #dispatch_sync(queue,block) sync 同步隊(duì)列,dispatch_sync 函數(shù)不會(huì)立即返回,即阻塞當(dāng)前線程,等待 block同步執(zhí)行完成。

 #3 :如何用GCD同步若干個(gè)異步調(diào)用?
      dispatch_queue_t queue =    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      dispatch_group_t group = dispatch_group_create();
      dispatch_group_async(group, queue, ^{ /*加載圖片1 */ });
      dispatch_group_async(group, queue, ^{ /*加載圖片2 */ });
      dispatch_group_async(group, queue, ^{ /*加載圖片3 */ }); 
      dispatch_group_notify(group, dispatch_get_main_queue(), ^{
       // 合并圖片
 });
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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