C之run loop详解

Objective-C之run loop详解

不知道大家有没有想过这个问题,一个应用开始运行以后放在那里,如果不对它进行任何操作,这个应用就像静止了一样,不会自发的有任何动作发生,但是如果我们点击界面上的一个按钮,这个时候就会有对应的按钮响应事件发生。给我们的感觉就像应用一直处于随时待命的状态,在没人操作的时候它一直在休息,在让它干活的时候,它就能立刻响应。其实,这就是run loop的功劳。

一、线程与run loop

1.1线程任务的类型

再来说说线程。有些线程执行的任务是一条直线,起点到终点;而另一些线程要干的活则是一个圆,不断循环,直到通过某种方式将它终止。直线线程如简单的Hello World,运行打印完,它的生命周期便结束了,像昙花一现那样;圆类型的如操作系统,一直运行直到你关机。在IOS中,圆型的线程就是通过run loop不停的循环实现的。

1.2线程与run loop的关系

Run loop,正如其名,loop表示某种循环,和run放在一起就表示一直在运行着的循环。实际上,run loop和线程是紧密相连的,可以这样说run loop是为了线程而生,没有线程,它就没有存在的必要。Run loops是线程的基础架构部分,Cocoa和CoreFundation都提供了run loop对象方便配置和管理线程的run loop(以下都已Cocoa为例)。每个线程,包括程序的主线程(main thread)都有与之相应的run loop对象。

1.2.1主线程的run loop默认是启动的。

iOS的应用程序里面,程序启动后会有一个如下的main()函数:

intmain(intargc,char*argv[])

{

@autoreleasepool{

returnUIApplicationMain(argc, argv,nil,NSStringFromClass([appDelegateclass]));

}

}

重点是UIApplicationMain()函数,这个方法会为main thread设置一个NSRunLoop对象,这就解释了本文开始说的为什么我们的应用可以在无人操作的时候休息,需要让它干活的时候又能立马响应。

1.2.2对其它线程来说,run loop默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动,如果线程只是去执行一个长时间的已确定的任务则不需要。

1.2.3在任何一个Cocoa程序的线程中,都可以通过:

NSRunLoop *runloop = [NSRunLoopcurrentRunLoop];

来获取到当前线程的run loop。

1.3关于run loop的几点说明

1.3.1 Cocoa中的NSRunLoop类并不是线程安全的

我们不能再一个线程中去操作另外一个线程的run loop对象,那很可能会造成意想不到的后果。不过幸运的是CoreFundation中的不透明类CFRunLoopRef是线程安全的,而且两种类型的run loop完全可以混合使用。Cocoa中的NSRunLoop类可以通过实例方法:

– (CFRunLoopRef)getCFRunLoop;

获取对应的CFRunLoopRef类,来达到线程安全的目的。

1.3.2 Run loop的管理并不完全是自动的。

我们仍必须设计线程代码以在适当的时候启动run loop并正确响应输入事件,当然前提是线程中需要用到run loop。而且,我们还需要使用while/for语句来驱动run loop能够循环运行,下面的代码就成功驱动了一个run loop:

BOOLisRunning =NO;

do{

isRunning = [[NSRunLoopcurrentRunLoop]runMode:NSDefaultRunLoopModebeforeDate:[NSDatedistantFuture]];

}while(isRunning);

1.3.3 Run loop同时也负责autorelease pool的创建和释放

在使用手动的内存管理方式的项目中,会经常用到很多自动释放的对象,如果这些对象不能够被即时释放掉,会造成内存占用量急剧增大。Run loop就为我们做了这样的工作,每当一个运行循环结束的时候,它都会释放一次autorelease pool,同时pool中的所有自动释放类型变量都会被释放掉。

1.3.4 Run loop的优点

一个run loop就是一个事件处理循环,用来不停的监听和处理输入事件并将其分配到对应的目标上进行处理。如果仅仅是想实现这个功能,你可能会想一个简单的while循环不就可以实现了吗,用得着费老大劲来做个那么复杂的机制?显然,苹果的架构设计师不是吃干饭的,你想到的他们早就想过了。

首先,NSRunLoop是一种更加高明的消息处理模式,他就高明在对消息处理过程进行了更好的抽象和封装,这样才能是的你不用处理一些很琐碎很低层次的具体消息的处理,在NSRunLoop中每一个消息就被打包在input source或者是timer source(见后文)中了。

其次,也是很重要的一点,使用run loop可以使你的线程在有工作的时候工作,没有工作的时候休眠,这可以大大节省系统资源。

二、Run loop相关知识点

2.1输入事件来源

Run loop接收输入事件来自两种不同的来源:输入源(input source)和定时源(timer source)。两种源都使用程序的某一特定的处理例程来处理到达的事件。图-1显示了run loop的概念结构以及各种源。

需要说明的是,当你创建输入源,你需要将其分配给run loop中的一个或多个模式(什么是模式,下文将会讲到)。模式只会在特定事件影响监听的源。大多数情况下,run loop运行在默认模式下,但是你也可以使其运行在自定义模式。若某一源在当前模式下不被监听,那么任何其生成的消息只在run loop运行在其关联的模式下才会被传递。

图-1 Runloop的结构和输入源类型

看了哪些风景,遇到哪些人。尽管同学说,去旅行不在于记忆,

C之run loop详解

相关文章:

你感兴趣的文章:

标签云: