多线程中的timer
来源:互联网 发布:太极越狱9.32mac 编辑:程序博客网 时间:2024/05/20 10:11
目录
- 1. NSRunLoopCommonModes和Timer
- 2. NSThread和Timer
- 3. GCD中的Timer
返回目录
1. NSRunLoopCommonModes和Timer
当使用NSTimer
的scheduledTimerWithTimeInterval
方法时。事实上此时Timer会被加入到当前线程的Run Loop中,且模式是默认的NSDefaultRunLoopMode
。而如果当前线程就是主线程,也就是UI线程时,某些UI事件,比如UIScrollView
的拖动操作,会将Run Loop切换成NSEventTrackingRunLoopMode
模式,在这个过程中,默认的NSDefaultRunLoopMode
模式中注册的事件是不会被执行的。也就是说,此时使用scheduledTimerWithTimeInterval
添加到Run Loop中的Timer就不会执行。
所以为了设置一个不被UI干扰的Timer,我们需要手动创建一个Timer,然后使用NSRunLoop
的addTimer:forMode:
方法来把Timer按照指定模式加入到Run Loop中。这里使用的模式是:NSRunLoopCommonModes
,这个模式等效于NSDefaultRunLoopMode
和NSEventTrackingRunLoopMode
的结合。(参考Apple文档)
参考代码:
- (void)viewDidLoad{ [super viewDidLoad]; NSLog(@"主线程 %@", [NSThread currentThread]); //创建Timer NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(timer_callback) userInfo:nil repeats:YES]; //使用NSRunLoopCommonModes模式,把timer加入到当前Run Loop中。 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];}//timer的回调方法- (void)timer_callback{ NSLog(@"Timer %@", [NSThread currentThread]);}
输出:
主线程 <NSThread: 0x71501e0>{name = (null), num = 1}Timer <NSThread: 0x71501e0>{name = (null), num = 1}Timer <NSThread: 0x71501e0>{name = (null), num = 1}Timer <NSThread: 0x71501e0>{name = (null), num = 1}
返回目录
2. NSThread和Timer
上面讲的NSRunLoopCommonModes
和Timer中有一个问题,这个Timer本质上是在当前线程的Run Loop中循环执行的,因此Timer的回调方法不是在另一个线程的。那么怎样在真正的多线程环境下运行一个Timer呢?
可以先试试NSThread
。同上,我们还是会把Timer加到Run Loop中,只不过这个是在另一个线程中,因此我们需要手动执行Run Loop(通过NSRunLoop
的run
方法),同时注意在新的线程执行中加入@autoreleasepool
。
完整代码如下:
- (void)viewDidLoad{ [super viewDidLoad]; NSLog(@"主线程 %@", [NSThread currentThread]); //创建并执行新的线程 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread) object:nil]; [thread start];}- (void)newThread{ @autoreleasepool { //在当前Run Loop中添加timer,模式是默认的NSDefaultRunLoopMode [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(timer_callback) userInfo:nil repeats:YES]; //开始执行新线程的Run Loop [[NSRunLoop currentRunLoop] run]; }}//timer的回调方法- (void)timer_callback{ NSLog(@"Timer %@", [NSThread currentThread]);}
输出:
主线程 <NSThread: 0x7118800>{name = (null), num = 1}Timer <NSThread: 0x715c2e0>{name = (null), num = 3}Timer <NSThread: 0x715c2e0>{name = (null), num = 3}Timer <NSThread: 0x715c2e0>{name = (null), num = 3}
返回目录
3. GCD中的Timer
GCD中的Timer应该是最灵活的,而且是多线程的。GCD中的Timer是靠Dispatch Source来实现的。
因此先需要声明一个dispatch_source_t
本地变量:
@interface ViewController (){ dispatch_source_t _timer;}
接着通过dispatch_source_create
函数来创建一个专门的Dispatch Source,接着通过dispatch_source_set_timer
函数来设置Timer的参数,注意这里的时间参数有些蛋疼。
开始时间的类型是dispatch_time_t
,最好用dispatch_time
或者dispatch_walltime
函数来创建dispatch_time_t
对象。如果需要Timer立即执行,可以传入dispatch_time(DISPATCH_TIME_NOW, 0)
。
internal
和leeway
参数分别表示Timer的间隔时间和精度。类型都是uint64_t
。间隔时间的单位竟然是纳秒。可以借助预定义的NSEC_PER_SEC
宏,比如如果间隔时间是两秒的话,那interval
参数就是:2 * NSEC_PER_SEC
。
leeway
就是精度参数,代表系统可以延时的时间间隔,最高精度当然就传0。
然后通过dispatch_source_set_event_handler
函数来设置Dispatch Source的事件回调,这里当然是使用Block了。
最后所有dispatch_source_t
创建后默认都是暂停状态的,所以必须通过dispatch_resume
函数来开始事件监听。这里就代表着开始Timer。
完整代码:
NSLog(@"主线程 %@", [NSThread currentThread]);//间隔还是2秒uint64_t interval = 2 * NSEC_PER_SEC;//创建一个专门执行timer回调的GCD队列dispatch_queue_t queue = dispatch_queue_create("my queue", 0);//创建Timer_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);//使用dispatch_source_set_timer函数设置timer参数dispatch_source_set_timer(_timer, dispatch_time(DISPATCH_TIME_NOW, 0), interval, 0);//设置回调dispatch_source_set_event_handler(_timer, ^(){ NSLog(@"Timer %@", [NSThread currentThread]);});//dispatch_source默认是Suspended状态,通过dispatch_resume函数开始它dispatch_resume(_timer);
输出:
主线程 <NSThread: 0x711fab0>{name = (null), num = 1}Timer <NSThread: 0x713a380>{name = (null), num = 3}Timer <NSThread: 0x713a380>{name = (null), num = 3}Timer <NSThread: 0x713a380>{name = (null), num = 3}
- Android中的多线程-Timer
- 多线程中的timer
- timer是多线程中的一种吗?
- Java中的Timer和TimerTask来实现多线程
- java中的多线程包--- Timer的缺陷 用ScheduledExecutorService替代
- 多线程与Timer控件
- android 多线程3:Timer
- 多线程 定时器 Timer
- Java多线程--Timer
- 多线程与timer
- 一步一步学多线程-Timer
- Visual C#中的多线程编程---THREAD类,THREADPOOL类,TIMER类
- C# 中的timer控件与多线程之间的测试与分析
- C#多线程——Timer
- 【Java多线程】-Timer,TimerTask,ScheduledExecutorService
- C#多线程——Timer
- java多线程之定时器Timer
- (十三)java多线程之Timer
- Linux C 算法——查找
- LeetCode之Bit Manipulation题目汇总
- 删除一个用户下的所有表
- 【数位DP】bzoj1026: [SCOI2009]windy数
- qweqwe
- 多线程中的timer
- Spring MVC 返回类型为字符串时, 返回中文变成"?"处理
- Win7(64位系统)中用Python连接access数据库(access2010)
- 数据库中批量授权与回收权限
- Linux下mount命令解析
- Android绘图(二)
- 响应式网站设计与制作
- 小爬虫1.0
- 14:类初步使用