iOS线程问题汇总

   #1:如何使用dispatch source实现一个精准的定时器。
   dispatch source是一个监视某些类型事件的对象。当这些事件发生时,它自动将一个block放入一个dispatch queue的执行例程中。
   它支持所有kqueue所支持的事件以及mach端口、内建计时器支持(这样我们就不用使用超时参数来创建自己的计时器)和用户事件。
   首先定义倒计时接口需要的参数:
   TimeCountDown.h
     @class TimeCountDown;
     @protocol TimeCountDownDelegate <NSObject>
     @optional
     - (void)timeCountDownPerSecond;
     @end

     @interface TimeCountDown : NSObject

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

     //倒计时时间
     @property(assign,nonatomic) NSInteger timeInterval;

     //开始时间
    -(void)startTimer:(NSInteger)timeInterval;

     //停止时间
    -(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秒
     }
  });
}

 //获取分派源分派处理程序之前恢复
  - (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:线程死锁问题:
          - (void)viewDidLoad {
                   [super viewDidLoad];
                    dispatch_sync(dispatch_get_main_queue(), ^{
                         NSLog(@"同步线程处理block");
                     });
          }
    #死锁原因
     #1:dispatch_sync在等待block语句执行完成,而block语句需要在主线程里执行,所以dispatch_sync如果在主线程调用就会造成死锁
     #2:dispatch_sync是同步的,本身就会阻塞当前线程,也即主线程。而又往主线程里塞进去一个block,所以就会发生死锁。
     #dispatch_async(dispatch_get_global_queue(), ^{
     #async 在主线程中 创建了一个异步线程 加入 全局并发队列,async 不会等待     block 执行完成,立即返回
     });
     }
     分析这段代码:view DidLoad 在主线程中,也即dispatch_get_main_queue()中,执行到sync时向dispatch_get_main_queue()插入同步thread,sync会等到后面的block执行完成才返回。sync又在主队列里面,是个串行队列,sync是后面才加入的,前面一个是主线程,所以sync想执行block必须等待前一个主线程执行完成,而主线程却在等待sync返回,去执行后续工作,从而造成死锁。
 #2:dispatch_sync 和 dispatch_async 区别:
      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 异步队列,dispatch_async 函数会立即返回, block会在后台异步执行。
 #dispatch_sync(queue,block) sync 同步队列,dispatch_sync 函数不会立即返回,即阻塞当前线程,等待 block同步执行完成。

 #3 :如何用GCD同步若干个异步调用?
      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(), ^{
       // 合并图片
 });
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容