iOS中timer相关的延时调用,常见的有NSObject中的performSelector:withObject:afterDelay:这个方法在调用的时候会设置当前runloop中timer,还有一种延时,直接使用NSTimer来配置任务。

这两种方式都一个共同的前提,就是当前线程里面需要有一个运行的runloop并且这个runloop里面有一个timer。

我们知道:只有主线程会在创建的时候默认自动运行一个runloop,并且有timer,普通的子线程是没有这些的。这样就带来一个问题了,有些时候我们并不确定我们的模块是不是会异步调用到,而我们在写这样的延时调用的时候一般都不会去检查运行时的环境,这样在子线程中被调用的时候,我们的代码中的延时调用的代码就会一直等待timer的调度,但是实际上在子线程中又没有这样的timer,这样我们的代码就永远不会被调到。

下面的代码展示了performSelector和dispatch_time的不同

  1. /*
  2. 采用gcd的方式 延时添加到队列
  3. */
  4. -(void) testDispatch_after{
  5. dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3*NSEC_PER_SEC);
  6. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  7. dispatch_after(time, queue, ^{
  8. NSLog(@"3秒后添加到队列");
  9. });
  10. dispatch_release(queue);
  11. }
  12. -(void) testDelay{
  13. NSLog(@"testDelay被执行");
  14. }
  15. /*
  16. dispatch_barrier_async 栅栏的作用
  17. */
  18. -(void) testDispatch_Barrier{
  19. //dispatch_queue_t gcd = dispatch_queue_create("这是序列队列", NULL);
  20. dispatch_queue_t gcd = dispatch_queue_create("这是并发队列", DISPATCH_QUEUE_CONCURRENT);
  21. dispatch_async(gcd, ^{
  22. NSLog(@"b0");
  23. //这个selector不会执行,因为线程中没有runloop
  24. [self performSelector:@selector(testDelay) withObject:nil afterDelay:3];
  25. //代码会执行,因为采用了gcd方式
  26. [self testDispatch_after];
  27. });
  28. dispatch_release(gcd);
  29. }

在有多线程操作的环境中,这样performSelector的延时调用,其实是缺乏安全性的。我们可以用另一套方案来解决这个问题,就是使用GCD中的dispatch_after来实现单次的延时调用

解决方案一:

performSelector并不是没有办法保证线程安全。例如下面的代码就可以运行:

  1. [self performSelector:@selector(testDelay) onThread:[NSThread mainThread] withObject:nil waitUntilDone:NO];

指定了该selector在主线程中运行。

解决方案二:

  1. [self performSelector:@selector(testDelay) withObject:nil afterDelay:3 inModes:[NSArray arrayWithObject:NSDefaultRunLoopMode]];
  2. [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];

启动线程中runloop,因为每个线程就有个默认的runloop

解决方案三:

1. [self performSelector:@selector(printLog) withObject:nil afterDelay:2.0f inModes:[NSArray arrayWithObject:NSDefaultRunLoopMode]];

2.[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];

iOS 多线程下安全的使用定时器的更多相关文章

  1. ASP.NET MVC Filters 4种默认过滤器的使用【附示例】 数据库常见死锁原因及处理 .NET源码中的链表 多线程下C#如何保证线程安全? .net实现支付宝在线支付 彻头彻尾理解单例模式与多线程 App.Config详解及读写操作 判断客户端是iOS还是Android,判断是不是在微信浏览器打开

    ASP.NET MVC Filters 4种默认过滤器的使用[附示例]   过滤器(Filters)的出现使得我们可以在ASP.NET MVC程序里更好的控制浏览器请求过来的URL,不是每个请求都会响 ...

  2. 【iOS开发】多线程下NSOperation、NSBlockOperation、NSInvocationOperation、NSOperationQueue的使用

    http://blog.csdn.net/crycheng/article/details/21799611 本篇文章主要介绍下多线程下NSOperation.NSBlockOperation.NSI ...

  3. iOS多线程开发之GCD(中篇)

    前文回顾: 上篇博客讲到GCD的实现是由队列和任务两部分组成,其中获取队列的方式有两种,第一种是通过GCD的API的dispatch_queue_create函数生成Dispatch Queue:第二 ...

  4. iOS 多线程:『RunLoop』详尽总结

    1. RunLoop 简介 1.1 什么是 RunLoop? 可以理解为字面意思:Run 表示运行,Loop 表示循环.结合在一起就是运行的循环的意思.哈哈,我更愿意翻译为『跑圈』.直观理解就像是不停 ...

  5. iOS多线程编程指南

    iOS多线程编程指南(拓展篇)(1) 一.Cocoa 在Cocoa上面使用多线程的指南包括以下这些: (1)不可改变的对象一般是线程安全的.一旦你创建了它们,你可以把这些对象在线程间安全的传递.另一方 ...

  6. iOS多线程编程原理及实践

    摘要:iOS开发中,开发者不仅要做好iOS的内存管理,而且如果你的iOS涉及多线程,那你也必须了解iOS编程中对多线程的限制,iOS主线程的堆栈大小为1M,其它线程均为512KB,且这个限制开发者是无 ...

  7. iOS 多线程 GCD part3:API

    https://www.jianshu.com/p/072111f5889d 2017.03.05 22:54* 字数 1667 阅读 88评论 0喜欢 1 0. 预备知识 GCD对时间的描述有些新奇 ...

  8. iOS多线程开发之GCD(中级篇)

    前文回顾: 上篇博客讲到GCD的实现是由队列和任务两部分组成,其中获取队列的方式有两种,第一种是通过GCD的API的dispatch_queue_create函数生成Dispatch Queue:第二 ...

  9. iOS多线程主题

    下面是:2个并发进程.和2个并发线程的示意图: 下面介绍三种多线程技术(Thread.Cocoa Operation.Grand Central Dispatch): 1.最轻量级Thread(需要自 ...

随机推荐

  1. 软件工程课堂练习——N层电梯只停一层求乘客爬楼层数最少(基本方法+优化方法)

    题目: •石家庄铁道大学基础大楼一共有四部电梯,每层都有人上下,电梯在每层都停.信1201-1班的张一东觉得在每层都停觉得不耐烦. •由于楼层不太高,在上下课高峰期时时,电梯从一层上行,但只允许停在某 ...

  2. ELK:kibana使用的lucene查询语法

    kibana在ELK阵营中用来查询展示数据elasticsearch构建在Lucene之上,过滤器语法和Lucene相同 kibana4官方演示页面 全文搜索 在搜索栏输入login,会返回所有字段值 ...

  3. 【转】oracle查询不到表的问题

    ORACLE的问题解决:Ora-00942:表或视图不存在 分类: 数据库2006-07-05 00:15 10793人阅读 评论(4) 收藏 举报 oraclesqlmanager 由powerde ...

  4. Netsharp快速入门(之9) 基础档案(工作区3 添加商品菜单,以及在产品中打开商品界面)

    作者:秋时 杨昶   时间:2014-02-15  转载须说明出处 3.5.2  添加导航菜单 1.打开平台工具,插件和资源节点,选择创建导航菜单,打开创建向导 2.选择所属插件 3.选择在哪个分类下 ...

  5. IOS 8 关于 Touch ID

    一.什么是Touch ID? Touch ID是在iPhone 5s后的设备上出现的指纹识别.Apple在IOS 8中开放给第三方APP使用. 可以使用 Touch ID 来验证用户的身份,用户经验证 ...

  6. IIS8托管WCF服务

    WCF服务程序本身不能运行,需要通过其他的宿主程序进行托管才能调用WCF服务功能,常见的宿主程序有IIS,WAS,Windows服务,当然在学习WCF技术的时候一般使用控制台应用程序或WinForm程 ...

  7. Winform 打印PDF顺序混乱,获取打印队列

    工作中PDF打印顺序混乱着实让我疼痛了好久,其实决绝方法非常简单,但没有想到这个点子的时候确实让我走了很多弯路 这里文章写出来并不是为了炫耀什么,只是觉得发现些好东西就分享出来而已,同时也做个记录,方 ...

  8. smaa github iryoku

    dx10 demo 这东西我没法跑nsight ...这就坑大了 里面有个 RenderTargetCollection这个东西里面有很多 rendertargets 最让我苦恼的就是 sceneRT ...

  9. python实现web分页日志查看

    当我们维护一个网站时,无论前台还是后台,经常会出现各种个样的问题.有时候问题很难直观的发现,这个时候只能查看各种日志来跟踪问题.但是查看日志有各种个样的问题.首先,要用各种工具登陆到服务器,这个有时候 ...

  10. 户外物理渗透:终端机,客户端的web测试思路

    现在的客户端界面越做越好看了,很多用到了web技术,轻便.界面炫.更新快,但是这样web的缺点也就出来了,就是不稳定,容易受用户等因素影响. 因为很多客户端web是内嵌的,内部通信,所以很多对安全的考 ...