iOS多线程的初步研究(三)

弄清楚NSRunLoop确实需要花时间,这个类的概念和模式似乎是Apple的平台独有(iOS+MacOSX),很难彻底搞懂(iOS没开源,呜呜)。

官网的解释是说run loop可以用于处理异步事件,很抽象的说法。不罗嗦,先看看NSRunLoop几个常用的方法。

+ (NSRunLoop *)currentRunLoop; //获得当前线程的run loop

+ (NSRunLoop *)mainRunLoop; //获得主线程的run loop

- (void)run; //进入处理事件循环,如果没有事件则立刻返回。注意:主线程上调用这个方法会导致无法返回(进入无限循环,虽然不会阻塞主线程),因为主线程一般总是会有事件处理。

- (void)runUntilDate:(NSDate *)limitDate; //同run方法,增加超时参数limitDate,避免进入无限循环。使用在UI线程(亦即主线程)上,可以达到暂停的效果。

- (BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate; //等待消息处理,好比在PC终端窗口上等待键盘输入。一旦有合适事件(mode相当于定义了事件的类型)被处理了,则立刻返回;类同run方法,如果没有事件处理也立刻返回;有否事件处理由返回布尔值判断。同样limitDate为超时参数。

- (void)acceptInputForMode:(NSString *)mode beforeDate:(NSDate *)limitDate; //似乎和runMode:差不多(测试过是这种结果,但确定是否有其它特殊情况下的不同),没有BOOL返回值。

官网文档也提到run和runUntilDate:会以NSDefaultRunLoopMode参数调用runMode:来处理事件。

当app运行后,iOS系统已经帮助主线程启动一个run loop,而一般线程则需要手动来启动run loop。

使用run loop的一个好处就是避免线程轮询的开销,run loop在无事件处理时可以自动进入睡眠状态,降低CPU的能耗。

比如一般线程轮询的方式为:

while (condition)

{

  // waiting for new data

  sleep(1);

  // process current data

}

其实这种方式是很能消耗CPU时间片的,如果在UI线程中这样使用还会阻塞UI响应。而改用NSRunLoop来实现,则可大大改善线程的执行效率,而且不会阻塞UI(很神奇,呵呵。有点像javascript,用单线程实现多线程的效果)。上面的例子可以改为:

while (condition)

{

  // waiting for new data

  if ([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]])

  {

    // process current data

  }

}

接下来我们看看具体的例子,包括如何实现线程执行的关联同步(join),以及UI线程run loop的一般使用技巧等。

假设有个线程A,它会启动线程B,然后等待B线程的结束。NSThread是没有join的方法,用run loop方式实现就比较精巧。

NSThread *A; //global

A = [[NSThread alloc] initWithTarget:self selector:@selector(runA) object:nil]; //生成线程A

- (void)runA

{

  [NSThread detachNewThreadSelector:@selector(runB) toTarget:self withObject:nil]; //生成线程B

  while (1)

  {

    if ([[NSRunLoop currentRunLoop] runMode:@"CustomRunLoopMode" beforeDate:[NSDate distantFuture]]) //相当于join

    {

      NSLog(@"线程B结束");

      break;

    }

  }

}

- (void)runB

{

  sleep(1);

  [self performSelector:@selector(setData) onThread:A withObject:nil waitUntilDone:YES modes:@[@"CustomRunLoopMode"]];

}

实际运行时,过1秒后线程A也会自动结束。这里用到自定义的mode,一般在UI线程上调用run loop会使用缺省的mode。结合while循环,UI线程就可以实现子线程的同步运行(具体例子这里不再描述,可参看:http://www.cnblogs.com/tangbinblog/archive/2012/12/07/2807088.html)。

下面罗列调用主线程的run loop的各种方式,读者可以加深理解:

[[NSRunLoop mainRunLoop] run]; //主线程永远等待,但让出主线程时间片

[[NSRunLoop mainRunLoop] runUntilDate:[NSDate distantFuture]]; //等同上面调用

[[NSRunLoop mainRunLoop] runUntilDate:[NSDate date]]; //立即返回

[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10.0]]; //主线程等待,但让出主线程时间片,然后过10秒后返回

[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate: [NSDate distantFuture]]; //主线程等待,但让出主线程时间片;有事件到达就返回,比如点击UI等。

[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate: [NSDate date]]; //立即返回

[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate: [NSDate dateWithTimeIntervalSinceNow:10.0]]; //主线程等待,但让出主线程时间片;有事件到达就返回,如果没有则过10秒返回。

 
 
分类: ios
标签: ios多线程

iOS多线程的初步研究3的更多相关文章

  1. iOS多线程的初步研究(六)

    iOS多线程的初步研究(六) iOS平台提供更高级的并发(异步)调用接口,让你可以集中精力去设计需完成的任务代码,避免去写与程序逻辑无关的线程生成.运行等管理代码.当然实质上是这些接口隐含生成线程和管 ...

  2. iOS多线程的初步研究1

    iOS多线程的初步研究(一) 对于多线程的开发,iOS系统提供了多种不同的接口,先谈谈iOS多线程最基础方面的使用.产生线程的方式姑且分两类,一类是显式调用,另一类是隐式调用. 一.显示调用的类为NS ...

  3. iOS多线程的初步研究

    iOS多线程的初步研究(四) 理解run loop后,才能彻底理解NSTimer的实现原理,也就是说NSTimer实际上依赖run loop实现的. 先看看NSTimer的两个常用方法: + (NST ...

  4. iOS多线程的初步研究(一)-- NSThread

    对于多线程的开发,iOS系统提供了多种不同的接口,先谈谈iOS多线程最基础方面的使用.产生线程的方式姑且分两类,一类是显式调用,另一类是隐式调用. 一.显示调用的类为NSThread.一般构造NSTh ...

  5. iOS多线程的初步研究(六)-- NSOperation

    iOS平台提供更高级的并发(异步)调用接口,让你可以集中精力去设计需完成的任务代码,避免去写与程序逻辑无关的线程生成.运行等管理代码.当然实质上是这些接口隐含生成线程和管理线程的运行,从而更加简洁地实 ...

  6. iOS多线程的初步研究(三)-- NSRunLoop

    弄清楚NSRunLoop确实需要花时间,这个类的概念和模式似乎是Apple的平台独有(iOS+MacOSX),很难彻底搞懂(iOS没开源,呜呜). 官网的解释是说run loop可以用于处理异步事件, ...

  7. iOS多线程的初步研究(九)-- dispatch源

    dispatch源(dispatch source)和RunLoop源概念上有些类似的地方,而且使用起来更简单.要很好地理解dispatch源,其实把它看成一种特别的生产消费模式.dispatch源好 ...

  8. iOS多线程的初步研究(七)-- dispatch对象

    谈起iOS的dispatch(正式称谓是Grand Central Dispatch或GCD),不得不说这又是iOS(包括MacOSX)平台的创新,优缺点这里不讨论,只有当你使用时才能真正体会到.我们 ...

  9. iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行

    可以有两个办法让NSURLConnection在子线程中运行,即将NSURLConnection加入到run loop或者NSOperationQueue中去运行. 前面提到可以将NSTimer手动加 ...

随机推荐

  1. Swift语言指南(七)--语言基础之布尔值和类型别名

    原文:Swift语言指南(七)--语言基础之布尔值和类型别名 布尔值 Swift有一个基本布尔类型,叫做布尔(bool),布尔值又称逻辑值(logical),因为它只能为真(true)或假(false ...

  2. 拥抱大家庭,nodejs走thrift

    拥抱大家庭,nodejs走thrift.最贱的例子,nodejs与nodejs之间走thrift对传. 1,官网下载 http://mirrors.cnnic.cn/apache/thrift/0.9 ...

  3. cmd 跟踪路由

    cmd   命令   tracert  ip 地址 用 来 跟踪路由

  4. java中HashSet详解

    HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSe ...

  5. Github资源汇集

    Github资源汇集 突然发现申请博客园已经两年有余,没有发表过一篇文章,十分惭愧.言归正传,先分享一下两年来收集的部分编程资源,大部分为Github上的项目.虽然网上这样的分享已不在少数,但不如我理 ...

  6. java设计模式之六适配器模式(Adapter)

    适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题.主要分为三类:类的适配器模式.对象的适配器模式.接口的适配器模式.首先,我们来看看类的适配器模 ...

  7. hibernate缓存机制和事务隔离机制

    一级缓存( Session缓存) }         一级缓存的管理 ◦          应用程序调用Session的save().update().saveOrUpdate().get()或loa ...

  8. IS2009制作Oracle 静默安装包(一)感谢空白先生特许授权

    原文:IS2009制作Oracle 静默安装包(一)感谢空白先生特许授权 上一篇: MyEclipse中消除frame引起的“the file XXX can not be found.Please ...

  9. ASP.NET4.0新特性

    原文:ASP.NET4.0新特性 在以前试用VS2010的时候已经关注到它在Web开发支持上的一些变化了,为此我还专门做了一个ppt,当初是计划在4月12日那天讲的,结果因为莫名其妙的原因导致没有语音 ...

  10. each与list的用法

    each与list的用法(PHP学习) 1.each的用法 先看API array each ( array &$array ) api里是这么描述的:each — 返回数组中当前的键/值对并 ...