多线程iOS进阶指南iOS学习笔记

4.4 GCD->4.0 GCD 的定时器事件

2016-04-18  本文已影响276人  蓝田_Loto

本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正。


本文相关目录:
==================== 所属文集:4.0 多线程 ====================
4.1 多线程基础->1.0 进程 & 线程
······················ 2.0 多线程简介
4.2 pthread
4.3 NSThread->1.0 创建线程
····················· 2.0 线程属性
····················· 3.0 线程状态/线程生命周期
····················· 4.0 多线程安全隐患
····················· 5.0 线程间通讯和常用方法
4.4 GCD->1.0 GCD简介和使用
·············· 2.0 线程间的通信
·············· 3.0 其他用法
·············· 4.0 GCD 的定时器事件
4.5 NSOperation->1.0 NSOperation简介
························ 2.0 NSOperationQueue
························ 3.0 线程间通信
························ 4.0 自定义NSOperation
4.6 RunLoop - 运行循环
===================== 所属文集:4.0 多线程 =====================


实际上 RunLoop 底层也会用到 GCD 的东西,比如 RunLoop 是用 dispatch_source_t实现的 Timer。但同时 GCD 提供的某些接口也用到了 RunLoop, 例如 dispatch_async()。

当调用dispatch_async(dispatch_get_main_queue(), block)时,libDispatch 会向主线程的 RunLoop 发送消息,RunLoop会被唤醒,并从消息中取得这个 block,并在回调 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__()
里执行这个 block。但这个逻辑仅限于 dispatch 到主线程,dispatch 到其他线程仍然是由 libDispatch 处理的。


【区别】NSTimer & GCD 的定时器:

代码示例:当滚动文字的时候,是不会影响 GCD的定时器的

#import "ViewController.h"

@interface ViewController ()
// 定时器 (这里不用带*,因为dispatch_source_t就是个类,内部已经包含了*)
@property(nonatomic, strong) dispatch_source_t timer;
@end

@implementation ViewController

int count = 0;

- (void)viewDidLoad {
  [super viewDidLoad];

  // 1、获得队列
  //    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
  dispatch_queue_t queue = dispatch_get_main_queue();

  // 2、创建一个定时器 (dispatch_source_t本质还是个OC对象)
  self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

  // 3、设置定时器的各种属性(几时开始任务,每隔多长时间执行一次)

  // 触发时间(何时开始执行第一个任务)
  // 比当前时间晚1秒
  dispatch_time_t start =
      dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
  // 马上就执行
  //  dispatch_time_t start1 = DISPATCH_TIME_NOW;

  // 时间间隔。GCD的时间参数,一般是纳秒(1秒 == 10的9次方纳秒)
  uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC);

  // 设置定时器的各种属性:比当前时间晚1秒开始,每隔1s 执行一次
  // 参数:(1)定时器名字 (2)触发时间 (3)时间间隔 (4)0
  dispatch_source_set_timer(self.timer, start, interval, 0);

  // 4、设置定时器的内部回调
  dispatch_source_set_event_handler(self.timer, ^{

    NSLog(@"1------------%@", [NSThread currentThread]);

    count++;

    if (count == 4) {
      NSLog(@"1------------count=%d", count);
      // 取消定时器
      dispatch_cancel(self.timer);
      self.timer = nil;
    }

  });

  // 5、启动定时器
  dispatch_resume(self.timer);
  NSLog(@"启动1------------");
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

  // 1、获得队列
  //    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
  dispatch_queue_t queue = dispatch_get_main_queue();

  // 2、创建一个定时器 (dispatch_source_t本质还是个OC对象)
  self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

  // 3、设置定时器的各种属性(几时开始任务,每隔多长时间执行一次)

  // 触发时间(何时开始执行第一个任务)
  // 比当前时间晚1秒
  dispatch_time_t start =
      dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));
  // 马上就执行
  //  dispatch_time_t start1 = DISPATCH_TIME_NOW;

  // 时间间隔。GCD的时间参数,一般是纳秒(1秒 == 10的9次方纳秒)
  uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC);

  // 设置定时器的各种属性:比当前时间晚1秒开始,每隔1s 执行一次
  // 参数:(1)定时器名字 (2)触发时间 (3)时间间隔 (4)0
  dispatch_source_set_timer(self.timer, start, interval, 0);

  // 4、设置定时器的内部回调
  dispatch_source_set_event_handler(self.timer, ^{

    NSLog(@"2------------%@", [NSThread currentThread]);

    count++;

    if (count == 6) {
      NSLog(@"2------------count=%d", count);
      // 取消定时器
      dispatch_cancel(self.timer);
      self.timer = nil;
    }

  });

  // 5、启动定时器
  dispatch_resume(self.timer);
  NSLog(@"启动2------------");
}

- (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];
  // Dispose of any resources that can be recreated.
}

@end

打印结果:

GCD 定时器[1838:94718] 启动1------------
GCD 定时器[1838:94718] 1------------<NSThread: 0x7fb853600430>{number = 1, name = main}
GCD 定时器[1838:94718] 1------------<NSThread: 0x7fb853600430>{number = 1, name = main}
GCD 定时器[1838:94718] 1------------<NSThread: 0x7fb853600430>{number = 1, name = main}
GCD 定时器[1838:94718] 1------------<NSThread: 0x7fb853600430>{number = 1, name = main}
GCD 定时器[1838:94718] 1------------count=4
GCD 定时器[1838:94718] 启动2------------
GCD 定时器[1838:94718] 2------------<NSThread: 0x7fb853600430>{number = 1, name = main}
GCD 定时器[1838:94718] 2------------<NSThread: 0x7fb853600430>{number = 1, name = main}
GCD 定时器[1838:94718] 2------------count=6

本文源码 Demo 详见 Github
https://github.com/shorfng/iOS_4.0_multithreading.git




作者:蓝田(Loto)
出处: 简书

如果你觉得本篇文章对你有所帮助,请点击文章末尾下方“喜欢”
如有疑问,请通过以下方式交流:
评论区回复微信(加好友请注明“简书+称呼”)发送邮件shorfng@126.com



本文版权归作者和本网站共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

上一篇下一篇

猜你喜欢

热点阅读