本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正。
本文相关目录:
==================== 所属文集: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 的定时器:
- CFRunLoopTimerRef 基本上说的就是 NSTimer,它受 RunLoop 的 Mode 影响
- GCD 的定时器不受 RunLoop 的 Mode 影响
代码示例:当滚动文字的时候,是不会影响 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
本文版权归作者和本网站共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
网友评论
demo已修改
从demo 里可以看出,在某一个方法中关闭定时器是不能再次开启的,但是在其他方法中如果想要开启就需要重新创建